LoginSignup
1
1

More than 5 years have passed since last update.

1日1個 @nabetani さんの作った問題を解くAdventCalendarの11日目です。

今日の問題は http://nabetani.sakura.ne.jp/hena/ord10haniwa/ にあります。

module Doukaku.Honeycomb (solve) where

type Point = (Double, Double)
type Direction = (Double, Double)

solve :: String -> String
solve = map snd . scanl (\ (p, _) d -> moveOn p d) ((0, 0), 'A') . map direct

direct :: Char -> Direction
direct '0' = (0, 1)
direct '1' = (cos (pi / 6), sin (pi / 6))
direct '2' = (cos (pi / 6), - sin (pi / 6))
direct '3' = (0, - 1)
direct '4' = (- cos (pi / 6), - sin (pi / 6))
direct '5' = (- cos (pi / 6), sin (pi / 6))

(.>.) :: Direction -> Direction -> Direction
(x, y) .>. (x', y') = (x + x', y + y')

move :: Point -> Direction -> Point
move (x, y) (dx, dy) = (x + dx, y + dy)

moveOn :: Point -> Direction -> (Point, Char)
moveOn p d = let p' = move p d
             in case whereIs p' of
               Just c -> (p', c)
               Nothing -> (p, '!')

points :: [(Point, Char)]
points = zip points' alpha
  where
    alpha = ['A' .. 'Z'] ++ ['a' .. 'k']
    circle n = reset $ concatMap (replicate n . direct) "234501"
      where
        reset [] = direct '0' : []
        reset ds = init ds ++ (last ds .>. direct '0') : []
    directions = concatMap circle [0..]
    points' = scanl move (0, 0) directions

whereIs :: Point -> Maybe Char
whereIs pt = fmap snd . head' . filter (inIt pt . fst) $ points
  where
    head' [] = Nothing
    head' xs = Just . head $ xs

inIt :: Point -> Point -> Bool
inIt (x, y) (cx, cy) = (x - cx) ^ (2 :: Int) + (y - cy) ^ (2 :: Int) < 0.5 ^ (2 :: Int)

六角のマス目を長方形のマス目にうまくマッピングして扱うのが定石ですが、あえて幾何的に解きました。
(0, 0)の座標からスタートして、1の長さずつxy平面を移動させています。
六角形に対する点の当たり判定が面倒だったので、半径0.5の円で代用しました。
余程誤差が蓄積しない限り六角形の中心付近を移動するはずですので、実用上これで十分です。

http://qiita.com/items/55641767510c2f9f235f に他の方の回答もありますので、見ると参考になるでしょう。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1