import Data.Array
import Data.Array.ST
import Data.List
import Data.STRef
withSTRef :: STRef s a -> (a -> ST s a) -> ST s ()
withSTRef ref k = do
a <- readSTRef ref
a' <- k a
writeSTRef ref a'
spiral size
| size
< 1 = error "spiral: size < 1" array
<- newArray
((0, 0), (size
-1, size
-1)) undefined pos
<- let start
= (size
-1) `
div`
2 in newSTRef (start, start, 1)
let move (dx,dy) = withSTRef pos $ \(x,y,n) -> do
n `
seq` writeArray array
(y
,x
) n
let right = move (1,0)
down = move (0,1)
left = move (-1,0)
up = move (0,-1)
let over n = do
replicateM_ n up
replicateM_ (n+1) right
let under n = do
replicateM_ n down
replicateM_ (n+1) left
spiralSize
:: Spiral
-> IntspiralSize = f . bounds where
f ((0,0), (w,h)) | w == h && w > 0 = w + 1
f
_ = error "Invalid spiral dimensions"
printSpiral
:: Spiral
-> IO ()printSpiral spiral = do
let size = spiralSize spiral
let items = [[spiral ! (i,j) | j <- [0..size-1]] | i <- [0..size-1]]
sumDiagonals
:: Spiral
-> IntsumDiagonals spiral =
let size = spiralSize spiral
s
= sum [spiral
! (i
,i
) + spiral
! (size
-i
-1, i
) | i
<- [0..size
-1]] in s-1 -- subtract 1 to undo counting the middle twice
main
= print $ sumDiagonals
$ spiral
1001
aW1wb3J0IENvbnRyb2wuTW9uYWQKaW1wb3J0IENvbnRyb2wuTW9uYWQuU1QKaW1wb3J0IERhdGEuQXJyYXkKaW1wb3J0IERhdGEuQXJyYXkuU1QKaW1wb3J0IERhdGEuTGlzdAppbXBvcnQgRGF0YS5TVFJlZgoKd2l0aFNUUmVmIDo6IFNUUmVmIHMgYSAtPiAoYSAtPiBTVCBzIGEpIC0+IFNUIHMgKCkKd2l0aFNUUmVmIHJlZiBrID0gZG8KICAgIGEgIDwtIHJlYWRTVFJlZiByZWYKICAgIGEnIDwtIGsgYQogICAgd3JpdGVTVFJlZiByZWYgYScKCnR5cGUgU3BpcmFsID0gQXJyYXkgKEludCxJbnQpIEludAoKc3BpcmFsIDo6IEludCAtPiBTcGlyYWwKc3BpcmFsIHNpemUKICAgIHwgc2l6ZSA8IDEgID0gZXJyb3IgInNwaXJhbDogc2l6ZSA8IDEiCiAgICB8IG90aGVyd2lzZSA9IHJ1blNUQXJyYXkgJCBkbwogICAgICAgIGFycmF5ICAgPC0gbmV3QXJyYXkgKCgwLCAwKSwgKHNpemUtMSwgc2l6ZS0xKSkgdW5kZWZpbmVkCiAgICAgICAgcG9zICAgICA8LSBsZXQgc3RhcnQgPSAoc2l6ZS0xKSBgZGl2YCAyCiAgICAgICAgICAgICAgICAgICAgaW4gbmV3U1RSZWYgKHN0YXJ0LCBzdGFydCwgMSkKICAgICAgICAKICAgICAgICBsZXQgbW92ZSAoZHgsZHkpID0gd2l0aFNUUmVmIHBvcyAkIFwoeCx5LG4pIC0+IGRvCiAgICAgICAgICAgIG4gYHNlcWAgd3JpdGVBcnJheSBhcnJheSAoeSx4KSBuCiAgICAgICAgICAgIHJldHVybiAoeCtkeCwgeStkeSwgbisxKQogICAgICAgIAogICAgICAgIGxldCByaWdodCA9IG1vdmUgKDEsMCkKICAgICAgICAgICAgZG93biAgPSBtb3ZlICgwLDEpCiAgICAgICAgICAgIGxlZnQgID0gbW92ZSAoLTEsMCkKICAgICAgICAgICAgdXAgICAgPSBtb3ZlICgwLC0xKQogICAgICAgIAogICAgICAgIGxldCBvdmVyIG4gPSBkbwogICAgICAgICAgICByZXBsaWNhdGVNXyBuICAgICB1cAogICAgICAgICAgICByZXBsaWNhdGVNXyAobisxKSByaWdodAogICAgICAgIGxldCB1bmRlciBuID0gZG8KICAgICAgICAgICAgcmVwbGljYXRlTV8gbiAgICAgZG93bgogICAgICAgICAgICByZXBsaWNhdGVNXyAobisxKSBsZWZ0CiAgICAgICAgCiAgICAgICAgc2VxdWVuY2VfICQgdGFrZSBzaXplICQgemlwV2l0aCAoJCkgKGN5Y2xlIFtvdmVyLCB1bmRlcl0pIFswLi5dCiAgICAgICAgCiAgICAgICAgcmV0dXJuIGFycmF5CgpzcGlyYWxTaXplIDo6IFNwaXJhbCAtPiBJbnQKc3BpcmFsU2l6ZSA9IGYgLiBib3VuZHMgd2hlcmUKICAgIGYgKCgwLDApLCAodyxoKSkgfCB3ID09IGggJiYgdyA+IDAgPSB3ICsgMQogICAgZiBfICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGVycm9yICJJbnZhbGlkIHNwaXJhbCBkaW1lbnNpb25zIgoKcHJpbnRTcGlyYWwgOjogU3BpcmFsIC0+IElPICgpCnByaW50U3BpcmFsIHNwaXJhbCA9IGRvCiAgICBsZXQgc2l6ZSA9IHNwaXJhbFNpemUgc3BpcmFsCiAgICBsZXQgaXRlbXMgPSBbW3NwaXJhbCAhIChpLGopIHwgaiA8LSBbMC4uc2l6ZS0xXV0gfCBpIDwtIFswLi5zaXplLTFdXQogICAgbWFwTV8gKHB1dFN0ckxuIC4gaW50ZXJjYWxhdGUgIlx0IiAuIG1hcCBzaG93KSBpdGVtcwoKc3VtRGlhZ29uYWxzIDo6IFNwaXJhbCAtPiBJbnQKc3VtRGlhZ29uYWxzIHNwaXJhbCA9CiAgICBsZXQgc2l6ZSA9IHNwaXJhbFNpemUgc3BpcmFsCiAgICAgICAgcyAgICA9IHN1bSBbc3BpcmFsICEgKGksaSkgKyBzcGlyYWwgISAoc2l6ZS1pLTEsIGkpIHwgaSA8LSBbMC4uc2l6ZS0xXV0KICAgICBpbiBzLTEgLS0gc3VidHJhY3QgMSB0byB1bmRvIGNvdW50aW5nIHRoZSBtaWRkbGUgdHdpY2UKCm1haW4gPSBwcmludCAkIHN1bURpYWdvbmFscyAkIHNwaXJhbCAxMDAx