2021-10-04 00:18:10 +00:00
|
|
|
import Data.List
|
|
|
|
import Data.Ord
|
|
|
|
import Text.Printf
|
2021-10-23 21:04:12 +00:00
|
|
|
import System.Environment
|
2021-10-04 00:18:10 +00:00
|
|
|
|
2021-10-23 21:04:12 +00:00
|
|
|
main = do
|
|
|
|
argv <- getArgs
|
|
|
|
listWordsUpToLength $ read $ argv !! 0
|
2021-10-04 00:18:10 +00:00
|
|
|
|
2021-10-09 21:33:28 +00:00
|
|
|
listWordsUpToLength :: Int -> IO ()
|
|
|
|
listWordsUpToLength n = do
|
2022-02-05 23:51:45 +00:00
|
|
|
putStr $ unlines [printf "%s %d/%d %f"
|
2022-01-31 01:09:56 +00:00
|
|
|
w
|
2022-02-03 17:33:20 +00:00
|
|
|
(p `div` gcd p q)
|
|
|
|
(q `div` gcd p q)
|
2022-02-05 23:51:45 +00:00
|
|
|
(atan (sqrt 3 / (2*q_/p_ + 1))) |
|
2022-02-03 17:33:20 +00:00
|
|
|
((p,q),w) <- wordlist (n `div` 2, n `div` 2),
|
2022-02-05 23:51:45 +00:00
|
|
|
let p_ = fromIntegral p :: Double,
|
|
|
|
let q_ = fromIntegral q :: Double,
|
2022-01-31 01:09:56 +00:00
|
|
|
length w <= n,
|
|
|
|
let x = 2*q + p,
|
|
|
|
let y = 2*p + q]
|
2021-10-09 21:33:28 +00:00
|
|
|
|
2022-02-05 23:51:45 +00:00
|
|
|
-- (sqrt 3 / 2 * fromIntegral p / (fromIntegral q + fromIntegral p / 2) :: Double) |
|
|
|
|
-- (slopeWord "bca" (orthogonalSlope (p,q))) |
|
|
|
|
|
2022-02-03 17:33:20 +00:00
|
|
|
wordlist :: (Int,Int) -> [((Int,Int),String)]
|
|
|
|
wordlist (pmax,qmax) = nub $
|
2022-01-31 01:09:56 +00:00
|
|
|
sortBy (comparing sl)
|
2022-02-03 17:33:20 +00:00
|
|
|
[((p `div` gcd p q, q `div` gcd p q), slopeWord "bca" (p,q)) |
|
2022-01-31 01:09:56 +00:00
|
|
|
p <- [0..pmax],
|
|
|
|
q <- [0..qmax],
|
|
|
|
q /= 0] -- use p /= 0 || q /= 0 for more symmetric output
|
2021-10-04 00:18:10 +00:00
|
|
|
where
|
|
|
|
sl ((p,q),_) = fromIntegral p / fromIntegral q
|
|
|
|
|
2021-10-09 21:33:28 +00:00
|
|
|
-- letters: reflection along e_1, reflection along e_2, other one; p,q >= 0
|
2022-02-03 17:33:20 +00:00
|
|
|
-- the "slope" (p,q) means the Euclidean vector q*e_1 + p*e_2, where e_1,e_2 are at a 60 degree angle
|
|
|
|
-- in Euclidean coordinates this is (q + p/2, sqrt(3)/2 * p)
|
|
|
|
slopeWord :: [Char] -> (Int,Int) -> String
|
|
|
|
slopeWord [x,y,z] (p,q)
|
|
|
|
| p > q = slopeWord [y,x,z] (q,p)
|
2021-10-09 21:33:28 +00:00
|
|
|
| otherwise = concat $ map word $ zipWith step list (tail list)
|
2021-10-04 00:18:10 +00:00
|
|
|
where
|
|
|
|
p_ = p `div` gcd p q
|
|
|
|
q_ = q `div` gcd p q
|
2021-10-05 01:12:47 +00:00
|
|
|
xmax = if (p_-q_) `mod` 3 == 0 then q_ else 3*q_ :: Int
|
|
|
|
list = [(x,(x*p) `div` q) | x <- [0..xmax]]
|
|
|
|
step (x1,y1) (x2,y2) = ((x1-y1) `mod` 3, y2-y1)
|
2021-10-09 21:33:28 +00:00
|
|
|
word (0,0) = [z,x]
|
|
|
|
word (1,0) = [y,z]
|
|
|
|
word (2,0) = [x,y]
|
|
|
|
word (0,1) = [z,y,x,y]
|
|
|
|
word (1,1) = [y,x,z,x]
|
|
|
|
word (2,1) = [x,z,y,z]
|
2022-02-03 17:33:20 +00:00
|
|
|
|
|
|
|
-- assuming p, q >= 0
|
|
|
|
orthogonalSlope :: (Int, Int) -> (Int, Int)
|
|
|
|
orthogonalSlope (p,q)
|
|
|
|
| p > q = (p-q, p+2*q)
|
|
|
|
| p < q = (q+2*p, q-p)
|
|
|
|
| otherwise = (1,0)
|