adventofcode

Happy Advent 2020! Please put answers in the pinned threads or create one if it does not exist yet. | https://github.com/adventofcode-clojurians/adventofcode-clojurians | Join the private leaderboard with code 217019-4a55b8eb
fellshard 2017-12-08T01:50:11.000008Z

I should've done part B more by hand, yeah. Automating it is a bit clumsy.

2017-12-08T01:55:22.000005Z

wow, so much to unpack

2017-12-08T01:57:12.000210Z

my strategy for finding the relevant node in part b was: * (ab)use tree-seq recursively to get a list of every nodes "tallied" weight - the weight it holds * group-by parent * filter for unbalanced groupings * get the one with the lowest tally (will be deepest in the tree)

💯 1
2017-12-08T02:00:20.000057Z

part 1 was simply "the node which supports, but isn't supported" -- i.e. (first (filter set-of-supportees supporters))

2017-12-08T02:07:57.000238Z

Ah, was looking for a walk/postwalk based answer 😄

2017-12-08T02:18:04.000100Z

Getting under 2ms for part 2 with your input on my loop/recur solution.. tree-seq solution turns out to be slower at ~14ms.. guess we can stop early once an unbalanced branch has a balanced set of children.

2017-12-08T02:18:32.000068Z

hmm tokyo timezone is good for getting the new questions when they come out, but not so great for discussion 😕

bhauman 2017-12-08T02:20:23.000177Z

darn I forgot about tree-seq

2017-12-08T02:22:18.000161Z

it's such a good swiss-army-knife of a function

2017-12-08T03:06:33.000006Z

I was inspired to write my first macro.. it's a let which you can drop *stop* into and it will throw an exception with the bindings up until that point as data https://gist.github.com/minikomi/b6e5a097970513934faf46f01f194725 when solving these problems I often have a long let within a function which somehow goes wrong..

fellshard 2017-12-08T04:57:02.000150Z

knuckle-crack Places, everyone! REPLs at the ready!

fellshard 2017-12-08T05:24:45.000107Z

Man. I love reductions

dyankowsky 2017-12-08T05:26:01.000132Z

yep

fellshard 2017-12-08T05:26:07.000087Z

Also, seems I'll need to dredge up my interpreter macros from last year...

dyankowsky 2017-12-08T05:26:21.000210Z

what kinds of stuff did you have?

fellshard 2017-12-08T05:26:35.000205Z

Not sure if I ever finished them tbh xD

fellshard 2017-12-08T05:27:02.000041Z

It was basically a way to write functions that could be partially applied at fixed points

dyankowsky 2017-12-08T05:28:41.000181Z

ah, I see

fellshard 2017-12-08T05:28:43.000162Z

So I can bind the parts of the operation I know at read-time, and then hand it the remaining context at execute-time

fellshard 2017-12-08T05:28:55.000206Z

Since that's a recurring pattern for these assembly-read type problems

dyankowsky 2017-12-08T05:29:17.000222Z

this is both the blessing and curse of Lisps

dyankowsky 2017-12-08T05:29:25.000165Z

you can make your own syntax!

fellshard 2017-12-08T05:29:26.000109Z

😅

dyankowsky 2017-12-08T05:29:30.000082Z

you can make your own syntax...

dyankowsky 2017-12-08T05:29:39.000108Z

(well, not syntax per se)

fellshard 2017-12-08T05:29:47.000111Z

Constructs

dyankowsky 2017-12-08T05:29:51.000017Z

sure

fellshard 2017-12-08T05:30:05.000255Z

In these cases, I found it easier than having to let-bind around an anonymous function

dyankowsky 2017-12-08T05:30:18.000095Z

oh sure

dyankowsky 2017-12-08T05:32:21.000146Z

one problem that I have is that, since I don't use clojure that much, I'm not savvy to all the clever things that I could do with builtins, so I worry that I sometimes rebuild things that already exist

dyankowsky 2017-12-08T05:33:08.000174Z

for example, I don't know if Clojure has any partial application support short of reader function literals

fellshard 2017-12-08T05:33:11.000012Z

Def. poke around the solutions here, you'll learn a lot of new functions that way, and how they're commonly (and sometimes uncommonly) leveraged. 4clojure used to be great for that, but I think it's down nowadays...

fellshard 2017-12-08T05:33:33.000079Z

https://clojuredocs.org/clojure.core/partial

fellshard 2017-12-08T05:35:21.000086Z

It's not common, I think, from what I've seen...

fellshard 2017-12-08T05:36:09.000025Z

Partly because for small arities, it's just quicker to use #(f bound-param %1 %2), or something like

dyankowsky 2017-12-08T05:37:40.000035Z

I'll stick that one in my toolbox

dyankowsky 2017-12-08T05:37:45.000199Z

but now I think it's bed time

dyankowsky 2017-12-08T05:37:49.000034Z

take care

2017-12-08T05:37:56.000104Z

goodnight 🙂

2017-12-08T05:41:21.000032Z

ah reductions is amazing haha

2017-12-08T05:46:52.000173Z

not so remarkable today

fellshard 2017-12-08T05:51:44.000099Z

It may be repetitive, but I really do end up getting into these micro-interpreter type problems >_>

fellshard 2017-12-08T05:51:55.000023Z

Maybe partially because Lisps are just so snappy at handling them

mikelis 2017-12-08T05:57:31.000116Z

hah, I had heard in passing about reductions but didn’t know it’s called that. I searched for scan, didn’t find it so wrote my own

fellshard 2017-12-08T05:59:27.000039Z

😄

fellshard 2017-12-08T05:59:58.000023Z

When a lot of these problems move from 'find the answer' to 'tell me something about the state along the way', reductions usually shows up

fellshard 2017-12-08T06:00:13.000025Z

So it also usually pays to build your solution as a reduction when feasible

mikelis 2017-12-08T06:00:13.000087Z

not a fan of the first element behavior though

(reductions str [1 2 3])
=> (1 "12" "123")

fellshard 2017-12-08T06:00:35.000091Z

Same as reduce, really

fellshard 2017-12-08T06:00:45.000033Z

oh wait

fellshard 2017-12-08T06:01:01.000105Z

No, yeah. Reduce always takes the first element as it stands if you don't provide a default

mikelis 2017-12-08T06:01:46.000112Z

well, there’s always (drop 1)

fellshard 2017-12-08T06:02:09.000077Z

d'oh

fellshard 2017-12-08T06:02:15.000092Z

That was delayed, probably a lambda spinning up

mikelis 2017-12-08T06:05:18.000180Z

lazy evaluation

😄 1
grzm 2017-12-08T06:08:00.000061Z

@mikelis.vindavs that's maybe a little much only an hour after it dropped

mikelis 2017-12-08T06:08:13.000062Z

good point

grzm 2017-12-08T06:08:15.000052Z

thanks 🙂

mikelis 2017-12-08T06:08:18.000126Z

sorry

mikelis 2017-12-08T06:08:46.000051Z

I kind of assumed this is a spoiler-alert zone

grzm 2017-12-08T06:09:35.000141Z

Yeah, I know what you mean. I'd give it at least another couple of hours. Or perhaps just point people to your repo. Then they know what they're in for.

mikelis 2017-12-08T06:10:45.000107Z

it’s just general bikeshedding, I should probably get to work instead 😅

grzm 2017-12-08T06:11:47.000004Z

FWIW, I chose a third way 🙂

mikelis 2017-12-08T06:12:55.000031Z

I was trying to save lines by trusting input https://github.com/axelarge/advent-of-code/blob/master/src/advent_of_code/2017/day8.clj#L15-L24

grzm 2017-12-08T06:15:29.000216Z

Nice. I like how you documented the lines. I've been getting lazier as the days have been getting on. I'll clean it up in the morning. Time for sleep for me.

grzm 2017-12-08T06:18:15.000242Z

oh, and how you reversed threading directions. That's one I'll have to keep in mind.

mikelis 2017-12-08T06:20:03.000056Z

you mean with ->> inside of ->?

mikelis 2017-12-08T06:21:14.000104Z

it’s neat, I only wish it worked the other way. the workaround there is to create a lambda

(->> {}
     (#(assoc % :x :y)))

2017-12-08T06:21:34.000184Z

or use as->

mikelis 2017-12-08T06:21:52.000016Z

I never know what to use for the name

2017-12-08T06:21:55.000092Z

love me some as->

2017-12-08T06:22:14.000012Z

I tend to go with $

mikelis 2017-12-08T06:22:37.000045Z

that’s a good choice, stands out.

mikelis 2017-12-08T06:23:15.000077Z

I’m loving this channel and the community so far!

2017-12-08T06:23:28.000033Z

could go with an emoji 😆

mikelis 2017-12-08T06:29:02.000173Z

still pretty nice & readable

fellshard 2017-12-08T07:39:26.000041Z

as-> is new to me! Much nicer to pick up than the magic wand / swiss arrows for most things, I bet

borkdude 2017-12-08T07:58:19.000191Z

Today was ok. I found the answer for part 2 while trying to find part 1 it turned out 😉. 5 ms performance.

borkdude 2017-12-08T08:15:17.000143Z

I have a security breach in there though 🙂

borkdude 2017-12-08T08:44:01.000035Z

(fixed the security breach)

val_waeselynck 2017-12-08T08:44:23.000186Z

Posted my solutions to day 8. Highlights: cond->, case, reductions. https://github.com/vvvvalvalval/advent-of-code-2017/blob/master/src/aoc2017/day08.clj

borkdude 2017-12-08T08:45:20.000274Z

Here’s mine: https://github.com/borkdude/aoc2017/blob/master/src/day8.clj

2017-12-08T08:47:18.000234Z

just using resolve 👐

val_waeselynck 2017-12-08T08:47:45.000159Z

@borkdude I find it intriguing that you used clojure.core/== instead of clojure.core/=, what's the rationale?

borkdude 2017-12-08T08:48:19.000075Z

Not needed, just to confuse new people 😉

😆 1
borkdude 2017-12-08T08:49:05.000224Z

@minikomi I had that too, but figured that when I would run someone elses input, bad things may happen on my machine: https://github.com/borkdude/aoc2017/commit/113de2ba459997544a6376a9944db41472d75bd6

2017-12-08T08:49:45.000165Z

yeah, i live on the edge

borkdude 2017-12-08T08:51:08.000205Z

a dec -511 if fs/wipe-harddisk-if-odd >= -4

😂 2
2017-12-08T08:51:16.000097Z

heh

2017-12-08T08:52:04.000165Z

@val_waeselynck mapcat vals - good one

2017-12-08T08:52:55.000220Z

i need to use mapcat more, always miss it

val_waeselynck 2017-12-08T09:04:46.000290Z

I noticed most people don't initialize the registers to 0, but this could lead to subtle bugs if all the registers that were updated end up being negative, and some of them are untouched you may end up with the wrong result (the right result being 0).

👍 3
2017-12-08T09:07:52.000243Z

ooh interesting edge case.

borkdude 2017-12-08T09:19:04.000335Z

true: lucky by input 🙂

2017-12-08T09:20:51.000063Z

(update registers reg-loc (fnil identity 0)) interesting line to write 😆

karlis 2017-12-08T11:16:15.000253Z

mine for today: https://github.com/skazhy/advent/blob/master/src/advent/2017/day8.clj Curious to see if anyone tried the creative approach of transforming the whole input to s-expressions & then evaling it.

borkdude 2017-12-08T11:24:55.000053Z

@karlis very similar to mine

borkdude 2017-12-08T11:56:33.000300Z

Solution in PostgreSQL: https://twitter.com/pg_xocolatl/status/939099677026340864

borkdude 2017-12-08T12:02:33.000285Z

@karlis Someone seems to have done this in Python: https://www.reddit.com/r/adventofcode/comments/7icnff/2017_day_8_solutions/dqxuwrz/

karlis 2017-12-08T12:03:36.000114Z

oh my 😄

bhauman 2017-12-08T12:08:06.000004Z

well that was easy 🙂

bhauman 2017-12-08T12:12:52.000304Z

darn why didn't I use max?

bhauman 2017-12-08T12:13:21.000214Z

I guess its still early

borkdude 2017-12-08T12:13:50.000168Z

@bhauman for fn-map I had: (defn op [sym] (get {’!= not= ’inc + ’dec -} sym (resolve sym)))

borkdude 2017-12-08T12:14:05.000121Z

but I changed it because I considered it a security hole - your version is safe

borkdude 2017-12-08T12:16:07.000158Z

anyway, this was an easy one for clojure at least

bhauman 2017-12-08T12:18:43.000260Z

Yeah, I saw that you did that, good call

bhauman 2017-12-08T12:19:20.000096Z

eval is temping here but ...

bhauman 2017-12-08T12:25:08.000082Z

yeah resolve is a better call as well

bhauman 2017-12-08T12:38:53.000115Z

I just started playing TIS-100, and I'm digging it, I'm super surpised by this.

👌 1
mfikes 2017-12-08T13:23:29.000170Z

My solutions are up. I used eval FWIW: https://github.com/mfikes/advent-of-code/blob/master/src/advent_2017/day_08.cljc

mfikes 2017-12-08T13:35:04.000203Z

@minikomi You can let == resolve to == FWIW

2017-12-08T13:41:56.000014Z

at first, i wanted to use syntax quote and eval

2017-12-08T13:42:51.000358Z

but then decided to go with an interpreter

mfikes 2017-12-08T13:43:27.000334Z

Yes, I used eval @karlis. It even works in self-hosted ClojureScript 🙂 https://github.com/mfikes/advent-of-code/blob/master/src/advent_2017/day_08.cljc#L22

mfikes 2017-12-08T13:45:55.000037Z

I didn't generate an entire namespace from the source input, if that's what you mean. 😀

orestis 2017-12-08T13:48:56.000434Z

Here’s mine - I had failed to cope with eval in the past due to the lack of access to the lexical context, so I just went with a plain reduce. https://github.com/orestis/adventofcode/blob/master/clojure/aoc/src/aoc/2017_day8.clj

mfikes 2017-12-08T13:48:58.000468Z

Nice @nooga Fairly compact result.

karlis 2017-12-08T13:49:00.000206Z

this is a pretty neat approach nevertheless!

2017-12-08T13:50:23.000227Z

I could definately golf it some more, avoid repeating solve1 code in solve2 and replace the loops with reduce 😄

2017-12-08T13:50:29.000054Z

thanks @mfikes

orestis 2017-12-08T13:53:45.000320Z

It seems a lot of people are using read-string for these, then destructuring the resulting vector… You wouldn’t usually do that, would you? Given the docs’ warning that read-string can eval code?

mfikes 2017-12-08T13:54:20.000311Z

@orestis If I'm reading your code correctly, you can write

(update context target #(op (or % 0) am))
as
(update context target (fnil op 0) am)

2017-12-08T13:54:53.000291Z

fnil is little known but really useful

orestis 2017-12-08T13:55:18.000104Z

Yep, I saw fnil in @nooga’s code and thought the same — I’ve yet to finish my 3rd read-through of clojure.core 😉

mfikes 2017-12-08T13:55:32.000019Z

@orestis Yeah, in real code I would parse things and not use read or eval. But this is AoC, one of the few places you can 🙂

orestis 2017-12-08T13:56:15.000361Z

@mfikes Ah, update can take extra args, no need to close over them. Thanks!

mfikes 2017-12-08T13:57:00.000261Z

@orestis Hey, even using (or x y) to deal with falsey x is a non-intuitive idiom that you learn to use after starting the journey 🙂

orestis 2017-12-08T13:57:48.000246Z

It’s a bummer that get offers a default value but update doesn’t. Breaks the symmetry.

mfikes 2017-12-08T13:57:59.000053Z

I failed to point that out in an early interview for code that was like (if x x y)

orestis 2017-12-08T13:58:23.000021Z

undefined || 0 is idiomatic JS though.

orestis 2017-12-08T13:58:50.000252Z

(I think! Who knows if there really is a concept of idiomatic JS these days)

mfikes 2017-12-08T14:00:20.000362Z

To be honest, I think the most profitable way I learned things is by reading other's code

orestis 2017-12-08T14:01:27.000359Z

Yep, that’s the value of AoC!

2017-12-08T14:02:17.000144Z

my dirty secret is that despite writing almost exclusively clj and cljs for the past 3 years, I still look at ClojureDocs every 5 minutes

2017-12-08T14:02:17.000607Z

😄

mfikes 2017-12-08T14:03:15.000447Z

I think Rich Hickey also looks at those docs

mfikes 2017-12-08T14:03:48.000018Z

I'm proud to have what I suspect is the slowest solution for day 8, coming in at 5 seconds

😮 1
mfikes 2017-12-08T14:04:25.000583Z

Going for 3 orders of magnitude slower than the fastest

2017-12-08T14:04:39.000336Z

I think it’s because I don’t pay close attention to simple things like argument lists when focusing at the problem I’m currently solving

2017-12-08T14:05:52.000249Z

yeah, I got that in emacs as well

mfikes 2017-12-08T14:06:02.000413Z

Cool!

2017-12-08T14:06:31.000581Z

but often you will be thinking “huh, does re in clojure.string/split have to be re or can it be a string”

2017-12-08T14:06:36.000120Z

or something

2017-12-08T14:06:47.000462Z

btw. my solution clocks at 5-6ms

mfikes 2017-12-08T14:06:49.000417Z

I always look that up, every time

😄 1
orestis 2017-12-08T14:10:50.000150Z

I would love if Dash could look up clojuredocs. I wonder if there’s a plugin for that.

orestis 2017-12-08T14:11:18.000222Z

Re speeds, part 1 5ms, part 2 15ms…

2017-12-08T14:12:15.000294Z

hm, as we figured out, it’s impossible to compare the performance unless we run each other’s code

2017-12-08T14:13:03.000092Z

but hey, if it’s 5ms it’s very decent

orestis 2017-12-08T14:13:32.000029Z

Today should be roughly comparable for everyone, assuming everyone has 1000 ops to run, there’s no loops or any other funky stuff going on there.

orestis 2017-12-08T14:14:03.000545Z

I have to clarify; 5ms is what time prints when running within CIDER. Not sure if the JVM is hot/cold/lukewarm/whatever.

borkdude 2017-12-08T14:16:59.000139Z

Both parts run in 5 ms for me (with criterium), but that’s because the first run already contained the solution for part 2

2017-12-08T14:17:11.000504Z

same

2017-12-08T14:17:26.000073Z

I mean, solve1 and solve2 are basically the same

2017-12-08T14:17:33.000009Z

in my code

orestis 2017-12-08T14:33:26.000265Z

@mfikes I like the use of spec to parse the values. I should start using that instead of regexes.

mfikes 2017-12-08T14:33:58.000158Z

Yeah, I wouldn't argue it is the right way. But the only way to find out is to try.

borkdude 2017-12-08T14:54:22.000752Z

for now read-string + destructuring is my favorite way, although spec sounds more interesting 🙂

bhauman 2017-12-08T14:58:33.000143Z

you can use edn/read-string for a safer version of read-string

bhauman 2017-12-08T14:59:09.000225Z

but really no need here

borkdude 2017-12-08T15:01:13.000265Z

edn/read-string is my default read-string 🙂

borkdude 2017-12-08T15:56:04.000313Z

I haven’t encountered a nil pointer with max… I think the behavior of (max) is undefined, like 1 / 0

cjmurphy 2017-12-08T15:56:59.000576Z

(max nil 0) gives a NPE for me

borkdude 2017-12-08T15:57:57.000805Z

@cjmurphy what about (maximum nil 10 11 nil)?

mfikes 2017-12-08T15:59:03.000231Z

fnil is only good out to 3 args as well

bhauman 2017-12-08T16:00:18.000076Z

its better to use keep to filter out nils

cjmurphy 2017-12-08T16:00:18.000323Z

Right 🙂

bhauman 2017-12-08T16:00:48.000117Z

or filter some?

mfikes 2017-12-08T16:01:01.000671Z

If you do that, then perhaps define a variant of max that can cope with no args

borkdude 2017-12-08T16:01:09.000118Z

but then you would maybe get (max) which is undefined

borkdude 2017-12-08T16:01:26.000438Z

it’s probably an x y problem

bhauman 2017-12-08T16:02:05.000247Z

basically a nil punning version of max is what we are talking about

mfikes 2017-12-08T16:02:10.000102Z

@cjmurphy Did you encounter this via (vals {}) returning nil?

cjmurphy 2017-12-08T16:02:33.000117Z

Maybe I'll make a max that works with a sequence and deals with nil that way...

mfikes 2017-12-08T16:02:42.000633Z

Curious what context it arises in

bhauman 2017-12-08T16:03:38.000114Z

`(defn maximum [& args] (when-let [args (not-empty (filter some? args))] (apply max args))) `

cjmurphy 2017-12-08T16:03:51.000247Z

@mfikes (apply maximum (vals new-memory)) yes

mfikes 2017-12-08T16:04:37.000223Z

In that case you should get an arity exception from max not a nil arg

cjmurphy 2017-12-08T16:04:57.000531Z

Yes I got that exception too.

mfikes 2017-12-08T16:04:58.000661Z

(apply max (vals {})) -> arity issue

orestis 2017-12-08T16:05:01.000465Z

I used (mapcat vals <seq>) and it took care of null values.

borkdude 2017-12-08T16:05:54.000128Z

I wonder how you got nils in the first place, I didn’t have this problem

orestis 2017-12-08T16:06:52.000515Z

If you use reductions in the second part, and you don’t use a pre-populated map, the first few steps will give you an empty map until the first successful operation.

mfikes 2017-12-08T16:07:23.000297Z

Cool mapcat solution. Perhaps (concat [1 2] nil [3 4])’s nil-punning should be in its docstring

borkdude 2017-12-08T16:07:31.000345Z

ah ok — I got my answer in the first part already

cjmurphy 2017-12-08T16:07:56.000008Z

@borkdude I got the NPE here: new-kept-highest (maximum kept-highest new-highest)

borkdude 2017-12-08T16:08:19.000108Z

@cjmurphy you could initialize kept-highest to 0, because this was the initial value of all registers

orestis 2017-12-08T16:08:47.000547Z

@mfikes I discovered it by accident.

cjmurphy 2017-12-08T16:09:46.000408Z

kept-highest is the 'running maximum' for part two, so not actually a register value.

mfikes 2017-12-08T16:09:54.000174Z

I ended up with this unsavory hack: (apply max (or (vals {}) [0]))

borkdude 2017-12-08T16:10:39.000181Z

@cjmurphy yeah, that’s why you could seed the running max with 0, because that’s the initial max

borkdude 2017-12-08T16:11:11.000276Z

(@cjmurphy assuming your doing something like reduce)

cjmurphy 2017-12-08T16:11:15.000696Z

Yes sure, I'll do that and see if any more NPEs

cjmurphy 2017-12-08T16:11:38.000156Z

I'm doing iterate.

borkdude 2017-12-08T16:11:45.000231Z

same idea

mfikes 2017-12-08T16:11:57.000511Z

@orestis Right. I also discovered (merge-with + [1] {0 2}) accidentally works, but I suspect the concat behavior is intended. Hrm.

cjmurphy 2017-12-08T16:13:26.000757Z

I'm thinking to initialize kept-highest to lowest possible value rather than 0.

borkdude 2017-12-08T16:14:04.000102Z

@cjmurphy I did it this way: https://github.com/borkdude/aoc2017/blob/master/src/day8.clj#L54

borkdude 2017-12-08T16:14:39.000269Z

so 0 is the initial value of cur-max (or kept-highest)

cjmurphy 2017-12-08T16:18:03.000314Z

I intitialized kept-highest/cur-max to Long/MIN_VALUE and now no more nil problems with max. So good point that there should not be problems with nil with max in the first place.

cjmurphy 2017-12-08T16:19:31.000332Z

There would be a problem with 0 if all the register values were negative, and were always being set to negative.

borkdude 2017-12-08T16:20:25.000403Z

@cjmurphy The problem description states: > The registers all start at 0.

cjmurphy 2017-12-08T16:22:23.000329Z

Sure so no problem using either 🙂 I just like using the min possible value as the default for finding the maximum.

cjmurphy 2017-12-08T16:25:37.000371Z

(If you have to use a default - if there really were none then nil would be better of course).

cjmurphy 2017-12-09T15:55:19.000008Z

If you attach any likelihood to the definition of 'held' requiring write then zero is not a good default. If you attach any likelihood to there being zero length input then it is better not to have a default at all. Good to be liberal with what you accept.

cjmurphy 2017-12-09T15:56:58.000064Z

@borkdude @mfikes ^ Sorry to still be banging on about yesterday's thing 🙂

borkdude 2017-12-09T15:58:02.000018Z

@cjmurphy the invariant is that held is the maximum of the previous state. 0 is exactly that.

cjmurphy 2017-12-09T15:59:27.000128Z

I just thought that it was possible that held means read and write. Very woolly word 'held'.

mfikes 2017-12-08T16:26:55.000426Z

Actually, I don’t really see a good solution to this whole mess given what Val pointed out. It seems you really need to initialize all your registers to 0. (Unless there is a way to accommodate not doing that.)

bhauman 2017-12-08T16:32:34.000082Z

I'm not so sure about that

bhauman 2017-12-08T16:33:38.000138Z

as registers aren't really defined before hand, the only case is where you have a register for a predicate value that isn't ever used

mfikes 2017-12-08T16:33:53.000104Z

Maybe you are right. To define a register, you have to touch it.

mfikes 2017-12-08T16:34:26.000598Z

Hmm. I guess you could read from a register but never write to it.

bhauman 2017-12-08T16:34:37.000365Z

yeah thats the off case but

bhauman 2017-12-08T16:35:04.000074Z

but it seems as if they are defining them dynamically

bhauman 2017-12-08T16:35:12.000384Z

specifications, specifications

mfikes 2017-12-08T16:35:12.000647Z

That register wound’t appear in your lazily-produced map, but has a theoretical value of 0

bhauman 2017-12-08T16:35:44.000650Z

although you could populate it when you check it fairly easily

mfikes 2017-12-08T16:35:50.000321Z

Yep

mfikes 2017-12-08T16:36:44.000538Z

b dec 5 if a < 1 would have been a good nasty input

borkdude 2017-12-08T16:51:10.000515Z

We have to generate inputs with spec and exercise the hell out of this

mfikes 2017-12-08T16:55:43.000394Z

Finally, a reason to have used Spec to parse!

(s/exercise ::instr 4)
([() []] [() []] [() []] [(?? MN -2 if *o -t/LR 1) [{:tgt ??, :upd MN, :val -2, :if if, :lhs *o, :cmp -t/LR, :rhs 1}]])

mfikes 2017-12-08T16:56:37.000481Z

One immediate bug this would ferret out for me is I have no function named MN. I would need to revise my s/def or do something.

borkdude 2017-12-08T16:58:08.000487Z

symbol? should be a set with the symbols you expect

borkdude 2017-12-08T16:59:31.000233Z

For generating register names: https://github.com/borkdude/aoc2015_day7/blob/master/day7.clj#L11

mfikes 2017-12-08T17:04:10.000429Z

Yes. This is perhaps another argument to use Spec over hand-rolled regex’s: You can more succinctly define valid input: https://github.com/mfikes/advent-of-code/commit/84774e390f5ea82568cf1c87308b125692611a0e#diff-ae7d8fc250d870104fa0c68af9f2e19a

👍 1
borkdude 2017-12-08T17:06:14.000443Z

In PureScript I’m expecting an ADT for these things, although you could also just do it with a set there

cjmurphy 2017-12-08T18:00:09.000362Z

If there really is no input you want the running maximum to end up at nil. So I settled with @bhauman's function that avoids both the arity exception and the NPE, with no default (i.e. nil default) for the running maximum in my code. Repeating his useful function here:

cjmurphy 2017-12-08T18:00:21.000458Z

(defn maximum [& args]
  (when-let [args (not-empty (filter some? args))]
    (apply max args)))

cjmurphy 2017-12-08T18:45:36.000245Z

If however you did use a default value, and you interpreted 'the highest value held in any register during this process' to exclude registers that are only ever read from, and also to exclude the from value of registers that are set, then it would be possible for the 'running maximum' to end up as negative, in which case Long/MIN_VALUE will result in a correct outcome as long as there are a positive number of registers set.

mfikes 2017-12-08T19:33:06.000317Z

@chrisblom Bravo! That's an extremely consumable solution, IMHO. By the way, I used eval as well. I also checked your solution and it works in Planck.

2017-12-08T20:01:12.000334Z

thanks!

spfeiffer 2017-12-08T20:38:35.000457Z

Wow…so elegant!

bhauman 2017-12-08T20:41:05.000483Z

Nice!

2017-12-08T21:50:12.000269Z

I was thinking about exactly this