-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.hs
78 lines (63 loc) · 3.48 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
module Main where
import Numeric -- (showIntAtBase)
import Data.Char -- (intToDigit)
import qualified Data.ByteString.Char8 as BC
calculateCell :: BC.ByteString -> BC.ByteString -> Char
calculateCell pState rule =
case BC.unpack pState of
"111" -> BC.head rule
"110" -> rule `BC.index` 1
"101" -> rule `BC.index` 2
"100" -> rule `BC.index` 3
"011" -> rule `BC.index` 4
"010" -> rule `BC.index` 5
"001" -> rule `BC.index` 6
"000" -> rule `BC.index` 7
padZeros :: Int -> BC.ByteString
padZeros n = BC.concat [BC.pack "0" | _ <- [1..n]]
binaryString :: Int -> BC.ByteString
binaryString x = do
let bs = BC.pack $ showIntAtBase 2 intToDigit x ""
if BC.length bs >= 8 then bs
else do
let missingZeros = 8 - BC.length bs
BC.append (padZeros missingZeros) bs
ensureLengthThree :: BC.ByteString -> BC.ByteString
ensureLengthThree s
| BC.length s == 3 = s
| otherwise = BC.append s (padZeros (3 - BC.length s))
padGen :: BC.ByteString -> Int -> BC.ByteString
padGen gen padTo = do
let missingZeros = padTo - (BC.length gen `quot` 2)
let zeros = padZeros missingZeros
BC.concat [zeros, gen, zeros]
generateLine :: BC.ByteString -> BC.ByteString -> BC.ByteString -> Int -> Int -> BC.ByteString
generateLine previousLine rule currentLine numberOfGenerations initialConditionLength
-- | BC.length currentLine == BC.length previousLine = padGen currentLine (numberOfGenerations - 1 + initialConditionLength)
| BC.length currentLine == BC.length previousLine = currentLine
| otherwise = do
let substr = BC.drop (BC.length currentLine - 1) (BC.take ((BC.length currentLine - 1)+3) previousLine) -- get substring of previous state
let psubstr = ensureLengthThree substr-- pad if needed to ensure length of three
let calulatedCell = calculateCell psubstr rule
let currentLineExtended = BC.append currentLine (BC.singleton calulatedCell)
generateLine previousLine rule currentLineExtended numberOfGenerations initialConditionLength
generate :: BC.ByteString -> BC.ByteString -> Int -> Int -> BC.ByteString -> Int -> BC.ByteString
generate previousLine rule generationCounter numberOfGenerations cellularAutomaton initialConditionLength
| generationCounter >= numberOfGenerations = cellularAutomaton
| otherwise = do
let thisLine = generateLine previousLine rule BC.empty numberOfGenerations initialConditionLength
generate thisLine rule (generationCounter + 1) numberOfGenerations (BC.append cellularAutomaton (BC.append (BC.pack "\n") thisLine)) initialConditionLength
main :: IO ()
main = do
contents <- BC.readFile "input.txt"
let [sRule, initialConditionsRaw, slines] = BC.lines contents
let rule = read (BC.unpack sRule) :: Int
let initialLength = BC.length initialConditionsRaw
let nlines = read (BC.unpack slines) :: Int
let initialConditions = padGen initialConditionsRaw (nlines + (initialLength `div` 2))
-- let initialConditions = padGen initialConditionsRaw (nlines + initialLength -1)
let lines = generate initialConditions (binaryString rule) 0 (nlines -1) initialConditions initialLength
let fileNamePrefix = BC.concat [BC.pack "results/r", BC.pack $ show rule, BC.pack "_g", slines, BC.pack "_i", initialConditionsRaw, BC.pack "_haskell"]
-- WRITE TO FILE SYSTEM AS IMAGE
let pbmText = BC.concat [BC.pack "P1\n", BC.pack $ show (BC.length initialConditions), BC.pack " ", BC.pack $ show nlines, BC.pack "\n", lines, BC.pack "\n"]
BC.writeFile (BC.unpack (BC.append fileNamePrefix (BC.pack ".pbm"))) pbmText