You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Circuit.hs 3.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. module Circuit (
  2. Fuel, Tank, cartanks, createTank, createFuel, evalChamber, checkChamber, evalFuel, checkFuel, build1, build, key_circuit, test_key_circ, key_input, key, big_input,
  3. Circuit(..), Chamber(..), Car(..), server_input, circ_from_perm,
  4. execCircuit, execCircuit2, checkCircuit, checkCircuits,
  5. permutations
  6. ) where
  7. import Encoding
  8. import CircuitBase
  9. import CircuitParser
  10. import CircuitSimulator
  11. -- import CircuitC
  12. import Data.List
  13. import Data.Maybe
  14. import Data.Packed
  15. type Fuel = [Tank]
  16. type Tank = Matrix Double
  17. -- IMPORANT functions:
  18. -- * build
  19. -- create a circuit for a desired fuel output
  20. -- example:
  21. -- build ""
  22. cartanks :: Car -> Int
  23. cartanks = (1+) . maximum . concat . map (\(Chamber upper _ lower) -> upper ++ lower) . chambers
  24. createTank :: [[Integer]] -> Tank
  25. createTank = fromLists . map (map fromIntegral)
  26. createFuel = map createTank
  27. evalChamber :: Fuel -> Chamber -> Matrix Double
  28. evalChamber tanks (Chamber upper _ lower) = product (map (tanks !! ) upper) - product (map (tanks !! ) lower)
  29. checkChamber :: Fuel -> Chamber -> Bool
  30. checkChamber tanks c@(Chamber upper main lower) = (all (>= 0) $ concat $ toLists diff) && (not main || (diff @@> (0,0)) > 0) where
  31. diff = evalChamber tanks c
  32. evalFuel :: Fuel -> Car -> [Matrix Double]
  33. evalFuel f = map (evalChamber f) . chambers
  34. checkFuel :: Fuel -> Car -> Bool
  35. checkFuel fuel car = checkfuel && all (checkChamber fuel) (chambers car) where
  36. checkfuel = if (all (>= 0) $ concat $ concat $ map toLists fuel) && all (\t -> (t @@> (0,0)) > 0) fuel then True else error "Fuel broken"
  37. -- zero everything:
  38. -- Circuit {outPin = 8, inPins = [2,9,4,5,-1,3,1,0,6,7]}
  39. -- basic blocks
  40. -- 0: 1R:2L1L0#X2L,2RX0#0R2R,0R1R0#0L1L:0L
  41. -- 1: 2L:2R1R0#2R1R,2L0R0#X0R,X0L0#1L0L:1L
  42. -- 2: 2R:2R1R0#2L1L,0R2L0#X0R,0LX0#1R0L:1L
  43. -- build circuit for needed output
  44. build1 s = let (p, pins) = step 4 [0,-1,1,6,2,3,5,7] (dropWhile (0 == ) $ reverse (key ++ (streamread s))) in Circuit p pins where
  45. step p gates [] = (p, gates)
  46. step p gates (x:xs) = let k = length gates in case x of
  47. 0 -> step k (gates ++ [k+4,k+2,k+5,p,k+1,k+3]) xs
  48. 1 -> step (k+2) (gates ++ [k+5,k+3,k+4,k+1,p,k]) xs
  49. 2 -> step (k+2) (gates ++ [k+5,k+3,k+1,k+4,k,p]) xs
  50. build s = let (p, pins) = step (-1) [] (reverse (key ++ (streamread s))) in Circuit p pins where
  51. step p gates [] = (p, gates)
  52. step p gates (x:xs) = let k = length gates in case x of
  53. 0 -> step k (gates ++ [k+4,k+2,k+5,p,k+1,k+3]) xs
  54. 1 -> step (k+2) (gates ++ [k+5,k+3,k+4,k+1,p,k]) xs
  55. 2 -> step (k+2) (gates ++ [k+5,k+3,k+1,k+4,k,p]) xs
  56. key_circuit = parseCircuit key_circuit_str
  57. key_circuit_str = "19L:12R13R0#1R12R,14R0L0#4R9L,9R10R0#3L8L,2L17R0#5L9R,15R1L0#10R13R,3L18R0#6L15L,5L11R0#13L12L,19R16R0#11R8R,2R7R0#11L10L,1R3R0#18L2L,8R4L0#16L2R,8L7L0#15R6R,6R0R0#14L0L,6L4R0#14R0R,12L13L0#17L1L,5R11L0#16R4L,10L15L0#17R7R,14L16L0#18R3R,9L17L0#19R5R,X18L0#X7L:19L"
  58. -- goal: Find a circuit with test_key_circ circ == True
  59. test_key_circ :: Circuit -> Bool
  60. test_key_circ circ = checkCircuit circ server_input key
  61. key_input :: [Trit]
  62. key_input = streamread "02222220210110011"
  63. key :: [Trit]
  64. key = execCircuit2 key_circuit key_input
  65. -- key: "11021210112101221"
  66. big_input = streamread "0120101201201020210210020210101010101110202022202020202001010210200102010201010201201020201201020120101202102021010120120210201201020120102102"