Day 3 and 4 kinda kicked my butt (plus I had work stuff both nights) but I finally finished [day 4](https://adventofcode.com/2018/day/4). It asks us to solve a scheduling problem, and the example even shows us a nice matrix we could use. I was sort of leery about trying another matrix based on my adventures on day 3. (I made what I thought was a reasonable-sized matrix and blew through all my memory, probably due to lazy execution or something.) So instead I went with a horribly compute-inefficient design. Input looks like this: ``` [1518-03-11 00:45] wakes up [1518-07-13 00:13] falls asleep [1518-11-02 23:56] Guard #3463 begins shift [1518-11-13 00:59] wakes up [1518-06-15 23:59] Guard #829 begins shift [1518-08-16 00:03] Guard #1399 begins shift [1518-09-18 00:19] wakes up [1518-08-30 00:56] wakes up [1518-04-22 00:32] falls asleep [1518-10-07 00:41] wakes up [1518-08-21 00:28] falls asleep ... ``` Parsing into a data structure isn't too bad, I haven't had to learn and break out a parser combinator yet. We can easily sort the timeline using standard alphanumeric ordering: ``` type Time = Int type GuardId = Int type GuardTotals = Map.Map GuardId Time type GuardSched = Array Int Int data Event = ShiftBegin Time GuardId | Sleep Time | Wake Time deriving Show timeToOffset :: String -> String -> Time -- timeToOffset h m = 60 * (read h) + (read m) -- oops, only minute matters timeToOffset h m = (read m) parseEvent :: String -> Event parseEvent s = case splitOneOf "[:] #" s of (_:_:h:m:_:kw:_) | kw == "wakes" -> Wake (timeToOffset h m) (_:_:h:m:_:kw:_) | kw == "falls" -> Sleep (timeToOffset h m) (_:_:h:m:_:kw:_:n:_) | kw == "Guard" -> ShiftBegin (timeToOffset h m) (read n ) _ -> undefined chronology = map parseEvent (sort (splitOn "\n" input) ) ``` Part one asks for which guard spent the most time sleeping, overall. (Not averaged!) I decided to do this as a fold, as that seems the right way in Haskell to "do something to every element of the list, maintaining some state." So I built a state machine as a function that I can call `foldl` on. ``` data GuardState = InitialState | Awake GuardId | Asleep GuardId Time deriving Show addOrInsert :: Int -> Maybe Int -> Maybe Int addOrInsert x (Just y) = Just (x+y) addOrInsert x Nothing = Just x updateSleep :: (GuardState,GuardTotals) -> Event -> (GuardState,GuardTotals) updateSleep (InitialState,m) (ShiftBegin time id) = ((Awake id),m) updateSleep (InitialState,m) _ = error "No shift begin" updateSleep (Awake id, m) (ShiftBegin time newId) = (Awake newId, m) updateSleep (Awake id, m) (Wake _) = error "Guard woke up when already awake." updateSleep (Awake id, m) (Sleep time) = (Asleep id time,m) updateSleep (Asleep _ _, _) (ShiftBegin _ _) = error "New shift started when guard asleep." updateSleep (Asleep _ _, _) (Sleep _) = error "Guard slept when already asleep." updateSleep (Asleep id start, m) (Wake end) = let minutes = end - start in (Awake id, Map.alter (addOrInsert minutes) id m) ``` The only surprising part was figuring out that most of the functions to modify a Map actually took a function rather than a new value, but OK. (I'm using `Data.Map.Strict` from containers-0.6.0.1.) Totaling up all the guard's sleep times thus becomes: ``` guardTotals = foldl' updateSleep (InitialState,Map.empty) chronology ``` Next we needed which *minute* that guard slept the most. I really did not think making my state machine drag along an array as well as a map was a great idea, but that would be most efficient. Part of the problem is that I don't know how to decompose this in a way that makes it easy to see what's being done on each state transition. There's probably some Haskell pattern to do this. So in the absence of something smart to do, I just copy/pasted a second version for computing the histogram of sleep per minute: ``` updateSched :: GuardId -> (GuardState,GuardSched) -> Event -> (GuardState,GuardSched) updateSched g (InitialState,m) (ShiftBegin time id) = ((Awake id),m) updateSched g (InitialState,m) _ = error "No shift begin" updateSched g (Awake id, m) (ShiftBegin time newId) = (Awake newId, m) updateSched g (Awake id, m) (Wake _) = error "Guard woke up when already awake." updateSched g (Awake id, m) (Sleep time) = (Asleep id time,m) updateSched g (Asleep _ _, _) (ShiftBegin _ _) = error "New shift started when guard asleep." updateSched g (Asleep _ _, _) (Sleep _) = error "Guard slept when already asleep." updateSched g (Asleep id start, a) (Wake end) | g == id = (Awake id, accum (+) a [(t,1) | t <- [start..(end-1)] ]) | g /= id = (Awake id, a ) emptySched = array (0,59) [ (i,0) | i <- [0..59] ] ``` We can get that array for a particular guard ``` schedule g = snd (foldl' (updateSched g) (InitialState,emptySched) chronology) ``` and after that it's just putting the pieces together. But this solution kinda sucks because it goes over the input N+1 times, where N is the number of guards. ``` guards = Map.keys (snd guardTotals) max2nd (g1,s1) (g2,s2) | s1 > s2 = (g1,s1) | s1 <= s2 = (g2,s2) sleepiestGuard = foldl1 max2nd (Map.assocs (snd guardTotals)) sleepiestMinute g = foldl1 max2nd (assocs (schedule g)) reorder guard (minute,count) = ((guard,minute),count) consistentSleeper = foldl1 max2nd [ reorder g (sleepiestMinute g) | g <- guards ] main :: IO () main = putStrLn (show (take 5 chronology)) >> putStrLn (show guardTotals) >> putStrLn ("Guard who slept the most: " ++ (show (fst sleepiestGuard))) >> putStrLn ("His schedule: " ++ (show (schedule (fst sleepiestGuard)))) >> putStrLn ("His sleepiest minute: " ++ show (fst (sleepiestMinute (fst sleepiestGuard)))) >> putStrLn ("Most consistent sleeper/minute: " ++ show (consistentSleeper)) ``` A better version would do one pass over the input and compute a list of schedules, each schedule a row of 0's and 1's for whether the guard is sleeping. Then we can add the rows for each guard, and from that we can compute both part 1 (sum the row and take the max over guards) and part 2 (max the rows and take the max over guards). Full version checked in here: https://github.com/mgritter/aoc2018/blob/master/day4/day4.hs
author | markgritter |
---|---|
permlink | advent-of-code-day-4-spoilers |
category | adventofcode |
json_metadata | {"tags":["adventofcode","programming","puzzle","haskell","functionalprogramming"],"links":["https://adventofcode.com/2018/day/4","https://github.com/mgritter/aoc2018/blob/master/day4/day4.hs"],"app":"steemit/0.1","format":"markdown"} |
created | 2018-12-06 07:24:39 |
last_update | 2018-12-06 07:31:45 |
depth | 0 |
children | 2 |
last_payout | 2018-12-13 07:24:39 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.817 HBD |
curator_payout_value | 0.222 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 6,375 |
author_reputation | 7,057,249,855,552 |
root_title | "Advent of Code Day 4 [spoilers]" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 76,437,012 |
net_rshares | 1,769,239,751,147 |
author_curate_reward | "" |
voter | weight | wgt% | rshares | pct | time |
---|---|---|---|---|---|
wackou | 0 | 21,241,342,416 | 0.32% | ||
lafona-miner | 0 | 190,457,362,898 | 5% | ||
mor | 0 | 2,532,317,665 | 100% | ||
eric-boucher | 0 | 1,753,089,556 | 0.54% | ||
anwenbaumeister | 0 | 12,334,654 | 1.08% | ||
mammasitta | 0 | 236,995,411 | 0.05% | ||
liberosist | 0 | 2,908,206,468 | 1.08% | ||
cmp2020 | 0 | 21,302,835,385 | 40% | ||
lemouth | 0 | 19,902,615,092 | 3.75% | ||
lamouthe | 0 | 2,136,841,753 | 5% | ||
lk666 | 0 | 88,677,539 | 0.54% | ||
remlaps1 | 0 | 16,370,129,368 | 40% | ||
curie | 0 | 29,706,775,916 | 1.08% | ||
cub1 | 0 | 91,801,469,938 | 40% | ||
hendrikdegrote | 0 | 503,582,438,827 | 1.08% | ||
vact | 0 | 20,666,271,548 | 1.08% | ||
golbang | 0 | 2,553,696,273 | 0.32% | ||
steemstem | 0 | 198,310,277,837 | 5% | ||
remlaps2 | 0 | 2,729,793,137 | 100% | ||
dna-replication | 0 | 1,366,715,321 | 5% | ||
lisa.palmer | 0 | 2,798,172,949 | 40% | ||
cub2 | 0 | 2,572,341,297 | 100% | ||
astronomyizfun | 0 | 2,229,754,289 | 40% | ||
davidfnck | 0 | 4,727,612,916 | 30% | ||
moksamol | 0 | 94,160,744 | 0.54% | ||
bloom | 0 | 20,793,122,255 | 5% | ||
iansart | 0 | 695,062,130 | 0.54% | ||
kryzsec | 0 | 1,986,838,305 | 4% | ||
yehey | 0 | 6,281,973,912 | 10% | ||
helo | 0 | 2,156,688,680 | 2.5% | ||
samminator | 0 | 1,449,620,501 | 2.5% | ||
locikll | 0 | 399,048,389 | 2.16% | ||
mahdiyari | 0 | 3,883,460,458 | 2.5% | ||
lorenzor | 0 | 4,695,838,285 | 50% | ||
aboutyourbiz | 0 | 171,907,186 | 1.08% | ||
alexander.alexis | 0 | 1,863,446,767 | 5% | ||
suesa | 0 | 115,365,417,206 | 25% | ||
cryptokrieg | 0 | 86,541,641 | 1.08% | ||
corsica | 0 | 2,225,885,893 | 5% | ||
fancybrothers | 0 | 554,588,205 | 1.5% | ||
howo | 0 | 6,743,752,933 | 2.5% | ||
tsoldovieri | 0 | 211,247,971 | 2.5% | ||
nitego | 0 | 83,917,250 | 0.32% | ||
neumannsalva | 0 | 108,204,299 | 0.54% | ||
wargof | 0 | 292,159,824 | 10% | ||
abigail-dantes | 0 | 84,917,354,052 | 5% | ||
zonguin | 0 | 120,506,480 | 1.25% | ||
alexzicky | 0 | 857,861,988 | 1.25% | ||
mountain.phil28 | 0 | 3,566,682,436 | 25% | ||
iamphysical | 0 | 12,979,236,785 | 90% | ||
zest | 0 | 925,881,445 | 2.5% | ||
felixrodriguez | 0 | 167,300,928 | 2.5% | ||
azulear | 0 | 2,956,725,124 | 100% | ||
psicoluigi | 0 | 328,490,052 | 50% | ||
massivevibration | 0 | 3,535,044,887 | 5% | ||
fbslo | 0 | 170,288,344 | 0.5% | ||
accelerator | 0 | 17,808,920,871 | 1.29% | ||
nicola71 | 0 | 268,424,166 | 0.87% | ||
espoem | 0 | 3,310,319,941 | 2% | ||
erikkun28 | 0 | 0 | 1% | ||
mayowadavid | 0 | 164,836,006 | 2.5% | ||
peaceandwar | 0 | 121,013,682 | 0.54% | ||
enzor | 0 | 104,408,051 | 5% | ||
jesusj1 | 0 | 82,444,573 | 100% | ||
carloserp-2000 | 0 | 32,678,200,304 | 100% | ||
gra | 0 | 1,849,201,949 | 5% | ||
steemtaker | 0 | 2,251,084,949 | 2% | ||
drmake | 0 | 540,098,913 | 0.54% | ||
guga34 | 0 | 86,038,754 | 3.75% | ||
amestyj | 0 | 1,719,706,214 | 50% | ||
skycae | 0 | 95,560,325 | 1.08% | ||
woolnami | 0 | 659,421,103 | 0.32% | ||
kenadis | 0 | 1,110,335,945 | 5% | ||
maticpecovnik | 0 | 181,804,172 | 2% | ||
robotics101 | 0 | 461,633,138 | 5% | ||
gentleshaid | 0 | 4,206,753,438 | 10% | ||
ivymalifred | 0 | 1,163,619,625 | 50% | ||
sco | 0 | 3,766,724,378 | 4.5% | ||
ennyta | 0 | 1,822,599,991 | 50% | ||
rharphelle | 0 | 1,035,301,893 | 25% | ||
stahlberg | 0 | 160,253,349 | 0.54% | ||
vjap55 | 0 | 362,073,384 | 100% | ||
langford | 0 | 306,161,048 | 5% | ||
bestsmiles | 0 | 101,094,418 | 50% | ||
mathowl | 0 | 12,996,680,282 | 45% | ||
silkroadgo | 0 | 1,414,822,321 | 0.32% | ||
terrylovejoy | 0 | 717,622,106 | 2% | ||
thabiggdogg | 0 | 94,830,789 | 0.54% | ||
traviseric | 0 | 233,985,939 | 50% | ||
yrmaleza | 0 | 945,706,191 | 50% | ||
mondodidave73 | 0 | 262,534,368 | 0.75% | ||
kingabesh | 0 | 113,701,424 | 2.5% | ||
miguelangel2801 | 0 | 782,661,434 | 50% | ||
didic | 0 | 487,938,587 | 0.54% | ||
emiliomoron | 0 | 1,784,950,572 | 50% | ||
dexterdev | 0 | 335,706,970 | 2.5% | ||
oghie | 0 | 551,764,200 | 50% | ||
robertbira | 0 | 466,583,577 | 1.25% | ||
alexdory | 0 | 1,949,074,456 | 2% | ||
flugschwein | 0 | 2,120,932,296 | 4.75% | ||
benleemusic | 0 | 155,203,114 | 0.1% | ||
lianaakobian | 0 | 516,132,676 | 5% | ||
kid1412 | 0 | 0 | 1% | ||
ulisesfl17 | 0 | 1,862,186,489 | 100% | ||
arac | 0 | 1,019,140,356 | 100% | ||
francostem | 0 | 649,661,104 | 5% | ||
smawkward | 0 | 1,153,141,996 | 25% | ||
ivan-g | 0 | 79,446,587 | 0.54% | ||
croctopus | 0 | 1,387,020,636 | 100% | ||
zipporah | 0 | 223,429,981 | 0.21% | ||
sissyjill | 0 | 71,617,985 | 7% | ||
deusjudo | 0 | 88,614,769 | 0.5% | ||
emmanuel293 | 0 | 100,213,568 | 25% | ||
morbyjohn | 0 | 128,444,311 | 7% | ||
positiveninja | 0 | 96,267,971 | 0.54% | ||
tomastonyperez | 0 | 5,444,805,286 | 50% | ||
elvigia | 0 | 4,487,526,154 | 50% | ||
lesmouths-travel | 0 | 201,751,961 | 3.75% | ||
effofex | 0 | 77,166,956 | 0.64% | ||
luiscd8a | 0 | 1,925,361,670 | 80% | ||
eniolw | 0 | 1,973,559,389 | 50% | ||
de-stem | 0 | 3,219,304,617 | 4.95% | ||
geadriana | 0 | 833,725,983 | 50% | ||
elpdl | 0 | 424,204,318 | 100% | ||
serylt | 0 | 1,440,705,704 | 4.9% | ||
josedelacruz | 0 | 2,571,125,861 | 50% | ||
joseangelvs | 0 | 818,260,602 | 100% | ||
viannis | 0 | 1,917,846,425 | 50% | ||
flores39 | 0 | 421,824,918 | 100% | ||
majapesi | 0 | 248,732,107 | 50% | ||
erickyoussif | 0 | 3,454,968,635 | 100% | ||
deholt | 0 | 135,232,397 | 5% | ||
sbi4 | 0 | 8,863,027,336 | 2% | ||
tcpolymath | 0 | 17,469,201,527 | 100% | ||
temitayo-pelumi | 0 | 339,122,046 | 5% | ||
yusvelasquez | 0 | 431,385,984 | 50% | ||
shookriya | 0 | 434,498,616 | 11.1% | ||
alexworld | 0 | 342,098,399 | 25% | ||
metama | 0 | 215,281,898 | 0.54% | ||
acont | 0 | 247,047,336 | 50% | ||
merlion | 0 | 1,058,803,476 | 1% | ||
anaestrada12 | 0 | 7,940,260,988 | 100% | ||
steemzeiger | 0 | 227,041,349 | 4.95% | ||
blewitt | 0 | 246,838,762 | 0.1% | ||
biomimi | 0 | 190,014,323 | 40% | ||
drsensor | 0 | 519,741,417 | 3% | ||
reyvaj | 0 | 784,052,449 | 2.5% | ||
jesusfl17 | 0 | 416,233,121 | 100% | ||
ilovecryptopl | 0 | 79,488,138 | 0.86% | ||
emsonic | 0 | 257,084,856 | 0.54% | ||
yomismosoy | 0 | 203,568,256 | 50% | ||
spbeckman | 0 | 4,160,081,208 | 100% | ||
call-me-howie | 0 | 349,140,537 | 0.54% | ||
mary11 | 0 | 281,085,793 | 75% | ||
doctorworm | 0 | 57,881,309,642 | 100% | ||
rgkmb-unofficial | 0 | 2,470,367,133 | 40% | ||
rgkmb | 0 | 176,410,423 | 40% | ||
wstanley226 | 0 | 1,694,424,049 | 50% | ||
gpcx86 | 0 | 1,999,171,971 | 25% | ||
reinaseq | 0 | 2,048,990,719 | 70% | ||
osariemen | 0 | 1,115,345,547 | 90% | ||
markgritter | 0 | 14,619,702,087 | 100% | ||
fran.frey | 0 | 1,801,543,550 | 50% | ||
jrevilla | 0 | 155,266,547 | 50% | ||
particleman | 0 | 25,959,119,150 | 100% | ||
cmp2020-lite | 0 | 148,809,064 | 40% | ||
remlaps-lite | 0 | 152,905,207 | 40% | ||
themesopotamians | 0 | 4,496,074,881 | 50% | ||
m-ashurbanipal | 0 | 576,766,965 | 100% | ||
m-gilgamesh | 0 | 1,443,936,917 | 100% | ||
stem-espanol | 0 | 31,149,165,991 | 100% | ||
praditya | 0 | 649,577,427 | 24% | ||
xeliram | 0 | 246,931,126 | 50% | ||
giulyfarci52 | 0 | 320,463,930 | 50% | ||
homefree | 0 | 96,435,540 | 11.1% | ||
nfc | 0 | 10,360,208,200 | 1% | ||
stem.witness | 0 | 1,099,420,116 | 5% | ||
monkeycatwithowl | 0 | 518,625,739 | 100% | ||
wilmer14molina | 0 | 150,312,625 | 10% | ||
kingnosa | 0 | 51,171,827 | 50% | ||
amin-ove | 0 | 88,394,930 | 50% | ||
blockmonster | 0 | 312,252,996 | 30% | ||
hairgistix | 0 | 154,858,300 | 0.54% | ||
huilco | 0 | 227,871,260 | 50% | ||
steemmyphoto | 0 | 558,341,047 | 100% |
<div class='text-justify'> <div class='pull-left'> <br /> <center> <img width='125' src='https://i.postimg.cc/9FwhnG3w/steemstem_curie.png'> </center> <br/> </div> <br /> <br /> This post has been voted on by the **SteemSTEM** curation team and voting trail in collaboration with **@curie**. <br /> If you appreciate the work we are doing then consider [voting](https://www.steemit.com/~witnesses) both projects for witness by selecting [**stem.witness**](https://steemconnect.com/sign/account_witness_vote?approve=1&witness=stem.witness) and [**curie**](https://steemconnect.com/sign/account_witness_vote?approve=1&witness=curie)! <br /> For additional information please join us on the [**SteemSTEM discord**]( https://discord.gg/BPARaqn) and to get to know the rest of the community! </div>
author | steemstem |
---|---|
permlink | re-markgritter-advent-of-code-day-4-spoilers-20181206t104332985z |
category | adventofcode |
json_metadata | {"app":"bloguable-bot"} |
created | 2018-12-06 10:43:36 |
last_update | 2018-12-06 10:43:36 |
depth | 1 |
children | 0 |
last_payout | 2018-12-13 10:43:36 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 800 |
author_reputation | 262,017,435,115,313 |
root_title | "Advent of Code Day 4 [spoilers]" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 76,443,338 |
net_rshares | 0 |
This story was recommended by Steeve to its users and upvoted by one or more of them. Check @steeveapp to learn more about Steeve, an AI-powered Steem interface.
author | steevebot |
---|---|
permlink | re-markgritter-advent-of-code-day-4-spoilers-vote-beneficiaries |
category | adventofcode |
json_metadata | {"tags":["adventofcode"],"app":"steeve/0.1","format":"markdown"} |
created | 2018-12-12 08:53:48 |
last_update | 2018-12-12 08:53:48 |
depth | 1 |
children | 0 |
last_payout | 2018-12-19 08:53:48 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 164 |
author_reputation | 1,016,697,284,644 |
root_title | "Advent of Code Day 4 [spoilers]" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 76,727,184 |
net_rshares | 203,070,718 |
author_curate_reward | "" |
voter | weight | wgt% | rshares | pct | time |
---|---|---|---|---|---|
mor | 0 | 203,070,718 | 10% |