Advertisement
Guest User

AoC 2018 day 4 in Factor

a guest
Dec 4th, 2018
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.82 KB | None | 0 0
  1. USING: accessors assocs calendar classes.tuple fry grouping
  2. io.encodings.utf8 io.files kernel literals make math math.order
  3. math.ranges math.statistics math.vectors parser prettyprint
  4. regexp sequences sequences.extras sets sorting.slots splitting ;
  5. IN: aoc2018.day4
  6.  
  7. : get-input ( -- seq ) "input4.txt" utf8 file-lines ;
  8.  
  9. TUPLE: entry ts event ;
  10. C: <entry> entry
  11.  
  12. : parse-date ( str -- timestamp )
  13. "- :" split [ parse-number ] map ${ 0 0 hours } append
  14. timestamp slots>tuple ;
  15.  
  16. : parse-entry ( str -- entry )
  17. R/ \] / re-split "" map-like first2 [ rest parse-date ]
  18. [ <entry> ] bi* ;
  19.  
  20. : get-entries ( -- entries )
  21. get-input [ parse-entry ] map { { ts>> <=> } } sort-by ;
  22.  
  23. : parse-id ( str -- n ) R/ \d+/ first-match parse-number ;
  24.  
  25. ! Is this entry the beginning of a shift?
  26. : transition? ( entry -- ? ) event>> "G" head? ;
  27.  
  28. ! Construct a sequence containing the indices at which a new
  29. ! guard takes over.
  30. : find-transition-indices ( entries -- indices )
  31. [ [ swap transition? [ , ] [ drop ] if ] each-index ] { }
  32. make ;
  33.  
  34. ! Group the entries that belong together in a single shift.
  35. : separate-shifts ( -- shifts )
  36. get-entries dup find-transition-indices differences
  37. [ [ cut [ , ] dip ] each , ] { } make ;
  38.  
  39. ! Convert a shift from { ~entry~ ~entry~ ... } to
  40. ! { sleep-time wake-time sleep-time wake-time ... } guard-id
  41. : pare-shift ( seq -- sleep-times id )
  42. [ rest-slice [ ts>> minute>> ] map ]
  43. [ first event>> parse-id ] bi ;
  44.  
  45. ! Build a hashtable of sleep and wake times by guard id.
  46. : build-db ( -- ht )
  47. H{ } clone dup separate-shifts [ pare-shift rot push-at ]
  48. with each ;
  49.  
  50. : time-asleep ( minutes -- n )
  51. 2 group [ first2 swap - ] map-sum ;
  52.  
  53. : total-time-asleep ( shifts -- n ) [ time-asleep ] map-sum ;
  54.  
  55. : max-index ( seq -- n ) [ supremum ] [ index ] bi ;
  56.  
  57. : find-sleepiest-guard ( db -- id )
  58. [ total-time-asleep ] assoc-map unzip max-index swap nth ;
  59.  
  60. : time-manifest ( db -- seq )
  61. dup find-sleepiest-guard swap at
  62. [ 2 group [ first2 [a,b) ] map ] map ;
  63.  
  64. : minute-sleepiness ( tm m -- n )
  65. '[ [ _ swap member? ] any? ] map [ t = ] count ;
  66.  
  67. : find-sleepiest-minute ( tm -- n )
  68. 60 <iota> [ minute-sleepiness ] with map max-index ;
  69.  
  70. : part1 ( db -- )
  71. [ find-sleepiest-guard ]
  72. [ time-manifest find-sleepiest-minute * ] bi . ;
  73.  
  74. : expand ( seq -- seq' )
  75. [ 1 ] dip 2 <groups> [ first2 [a,b) ] map concat 60 [ 0 ]
  76. replicate [ set-nths ] keep ;
  77.  
  78. : occurrences ( seq -- seq' ) [ expand ] [ v+ ] map-reduce ;
  79.  
  80. : most-frequent-id ( db -- id )
  81. [ occurrences supremum ] assoc-map unzip max-index swap nth
  82. ;
  83.  
  84. : most-frequent-minute ( id db -- n ) at occurrences max-index ;
  85.  
  86. : part2 ( db -- )
  87. [ most-frequent-id dup ] [ most-frequent-minute ] bi * . ;
  88.  
  89. : main ( -- ) build-db [ part1 ] [ part2 ] bi ;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement