Problem:
星座探し

問題

あなたは星空の写真の中から星座を探している．写真には必ず，探したい星座と同じ形・向き・大きさの図形がちょうど一つ含まれている．ただし，写真の中には星座を構成する星以外に余分な星が写っている可能性がある．

例えば，図 1 の星座は図 2 の写真に含まれている（丸で囲んで示した）．与えられた星座の星の座標を x 方向に 2， y 方向に −3 だけ平行移動すると写真の中の位置になる．

探したい星座の形と写真に写っている星の位置が与えられたとき，星座の座標を写真の中の座標に変換するために平行移動するべき量を答えるプログラムを書け．

図 1: 探したい星座

図 2: 星空の写真

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．

入力の 1 行目には探したい星座を構成する星の個数 m が書かれている．続く m 行には探したい星座を構成する m 個の星の x 座標と y 座標を示す整数が空白区切りで書かれている． m+2 行目には写真に写っている星の個数 n が書かれている．続く n 行には写真に写っている n 個の星の x 座標と y 座標を示す整数が空白区切りで書かれている．

星座を構成する m 個の星の位置はすべて異なる．また，写真に写っている n 個の星の位置はすべて異なる． 1 ≤ m ≤ 200， 1 ≤ n ≤ 1000 である．星の x 座標と y 座標はすべて 0 以上 1000000 以下である．

m が 0　のとき入力の終わりを示す. データセットの数は 5 を超えない．

出力

各データセットの出力は 1 行からなり， 2 個の整数を空白区切りで書く．これらは探したい星座の座標をどれだけ平行移動すれば写真の中の座標になるかを表す．最初の整数が x 方向に平行移動する量，次の整数が y 方向に平行移動する量である．

入出力例

入力例

5
8 5
6 4
4 3
7 10
0 10
10
10 5
2 7
9 7
8 10
10 2
1 2
8 1
6 7
6 0
0 9
5
904207 809784
845370 244806
499091 59863
638406 182509
435076 362268
10
757559 866424
114810 239537
519926 989458
461089 424480
674361 448440
81851 150384
459107 795405
299682 6700
254125 362183
50795 541942
0

出力例

2 -3
-384281 179674

入出力例の１つ目は上の図に対応している．

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in Haskell (judge verdict: Accepted)

import Control.Applicative
import Control.Monad
import Control.Monad.ST
import Data.Functor
import Data.Function
import Data.Monoid
import Data.Maybe
import Data.List
import qualified Data.Foldable as Foldable
import qualified Data.Set as Set
import Data.List.Split
import Data.Bits
import Data.Char
import Data.Ix
import Data.Ratio
import Data.Ord
import Data.Tuple
import Data.Array
--import Data.Array.Unboxed
import Data.Array.IO
import Data.Array.ST
import Data.IORef
import Data.STRef
-- import System.IO.Unsafe
 
readInt = read :: String -> Int
readDouble = read :: String -> Double
getInt = readLn :: IO Int
getInts = map readInt . words <$> getLine
getDouble = readLn :: IO Double
sjoin :: (Show a) => [a] -> String
sjoin = unwords . map show
cond :: a -> a -> Bool -> a
cond t f c = if c then t else f
apply2 :: (a -> a -> b) -> [a] -> b
apply2 f [x,y] = f x y
apply3 :: (a -> a -> a -> b) -> [a] -> b
apply3 f [x,y,z] = f x y z
apply4 :: (a -> a -> a -> a -> b) -> [a] -> b
apply4 f [x,y,z,w] = f x y z w
fnBin :: (b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d
fnBin op f g x = op (f x) $ g x
fnTuple :: (a -> b, a -> c) -> a -> (b, c)
fnTuple (f,g) a = (f a, g a)
replace :: (Eq a) => a -> a -> [a] -> [a]
replace x y = map (\z -> if z==x then y else z)
modifyArray :: (Ix i, MArray a e m) => a i e -> i -> (e -> e) -> m ()
modifyArray arr ix f = readArray arr ix >>= writeArray arr ix . f
-- end of templete

(x1,y1) >+< (x2,y2) = (x1+x2,y1+y2)
(x1,y1) >-< (x2,y2) = (x1-x2,y1-y2)


main = do
    n <- getInt
    when (n/=0) $ do
        ts <- map (apply2 (,)) <$> replicateM n getInts
        let base = head ts
        let dts = map (>-<base) ts
        m <- getInt
        ws <- map (apply2 (,)) <$> replicateM m getInts
        let wset = Set.fromList ws
        let (x,y) = (>-<base) $ fromJust $ find (\p -> all (flip Set.member wset) [p >+< d | d <- dts]) ws in putStrLn $ show x ++ " " ++ show y
        main