Advent of Code 2017

Advent of Code is a series of small programming puzzles for a variety of skill levels. They are self-contained and are just as appropriate for an expert who wants to stay sharp as they are for a beginner who is just learning to code. Each puzzle calls upon different skills and has two parts that build on a theme.

Other urls found in this thread:>.>.import

Day 1 in Rust:
const INPUT: &[u8] = b"1122";fn main() { println!("{}", INPUT .iter() .zip(INPUT[1..].iter().chain(std::iter::once(&INPUT[0]))) .filter(|&(a, b)| a == b) .map(|(a, _)| (a - b'0') as u32) .sum::() );}

Day 1 in C:

#include char INPUT[] = "1122";int main(){ unsigned int result = 0; unsigned int i; for (i = 0; i < sizeof(INPUT)-1; i++) { if (INPUT[i] == INPUT[(i+1)%(sizeof(INPUT)-1)]) { result += INPUT[i] - '0'; } } printf("%d\n", result); return 0;}

1 in Python
[code]#!/usr/bin/env python3

INPUT = "1122"

print(sum(map(lambda a, b: int(a) if a == b else 0, INPUT, INPUT[1:]+INPUT[0])))[code]

just noticed that there is a part 2: const INPUT: &str = "1212";fn main() { println!( "{}", solve( INPUT.chars().map(fuck_you_rust_why_are_closures_not_clone), INPUT.len() / 2 ) );}fn fuck_you_rust_why_are_closures_not_clone(c: char) -> u32 { c.to_digit(10).unwrap()}fn solve(iter: I, step: usize) -> u32 { iter.clone() .zip(iter.cycle().skip(step)) .filter(|&(a, b)| a == b) .map(|(a, _)| a) .sum()}

What is part 2? Do I need to log in to see it?

#include char INPUT[] = "123425";int main(){ unsigned int result = 0; unsigned int i; for (i = 0; i < sizeof(INPUT)-1; i++) { if (INPUT[i] == INPUT[(i+(sizeof(INPUT)-1)/2)%(sizeof(INPUT)-1)]) { result += INPUT[i] - '0'; } } printf("%d\n", result); return 0;}
#!/usr/bin/python3for INPUT in ["1212", "1221", "123425", "123123", "12131415"]: print(sum(map(lambda a, b: int(a) if a == b else 0, INPUT, INPUT[int(len(INPUT)/2):]+INPUT)))

PROC advent 1 = (STRING d)INT: IF LWB d > UPB d THEN 0 ELSE STRING e = d + d[LWB d], INT sum := 0; FOR i FROM LWB e TO UPB e - 1 DO IF e[i] = e[i + 1] THEN sum +:= IF INT x; char in string(e[i], x, "0123456789"[@0]) THEN x ELSE 0 FI FI OD; sum FI;printf(($g(0)l$, advent 1("1122"), advent 1("1111"), advent 1("1234"), advent 1("91212129")))



echo 1122 | awk '{split($0,c,"");r=0;for(i=1;i

do i get paid or win a job for solving these problems?

Look, you're trapped here forever. Solving these is an option to kill your boredom in this shithole and to show off languages.

thats what shitpostings for cunt

have you considered killing yourself?

Shut up and code.

My thoughts exactly...

I got this in python, nothing fancy:
line = open("input.txt", "r").readline();acum = 0;for i in range(0, len(line)): if line[i - 1] == line[i]: acum += int(line[i]);print(acum);
line = open("input.txt", "r").readline();acum = 0;for i in range(0, len(line)): if line[i - len(line) // 2] == line[i]: acum += int(line[i]);print(acum);

b-but user there's no other coding challenge sites

ITT faggots try to broadcast their Holla Forums awareness by posting their favourite esoteric languages that AREN'T used in INDUSTRY and then they argue over how 'superior' and 'expressive' their language is. How it will be the industry standard in 5 years. They say they are 'programmers', 'developers', and 'software engineers'. Yet they argue about programming languages instead of ACTUALLY programming. These faggots are more appropriately known as 'LARPers'. LARPers who write shitty code and will be replaced by more experienced streetshitters who write more functional, more maintainable, BETTER code.


spd-say -t child_female -p +100 faggot


Lighten up mate, these are only for fun.

who cares, faggot

Calm down and take your pills. Also
C, Python, Perl, Awk aren't used in the industry?

into the trash

Here's something to soothe your gay rage

Perl (theres a better solution but im tired rn)
use strict;use warnings "all";my @data = qw(1 1 2 2);#my @data = qw(1 1 1 1);#my @data = qw(1 2 3 4);#my @data = qw(9 1 2 1 2 1 2 9);my $sum = 0;my $last = $data[0];for (my $i = 1; $i < int (@data + 1); ++$i) { if ($data[$i % int @data] == $last) { $sum += $data[$i % int @data]; } $last = $data[$i];}print "$sum\n";

Here is the wizard version
use strict;use warnings "all";my $d = "1122";#my $d = "1111";#my $d = "1234";#my $d = "91212129";$d =~ m,^(\d),;$d .= $1;my $sum = 0;while ($d =~ m,(?=(\d)(\d)),g) { if ($1 == $2) { $sum += $1; }}print "$sum\n";

C double plus void inverse_captcha1(std::string input){ input.push_back(input[0]); std::cout


friend, you curse the crescent moon for vile acts of light pollution and you forget that the day-star will come around, too.
people using languages that interest them may not be professionals, but they are programmers, and their output is honest - it is clearly what it is.
true LARPing you will find on StackOverflow, where "is X suitable for Y?" will always get an earnest affirmative reply. Some motherfucker, because he likes Clojure a little bit, will cheerfully lay his name and reputation down and try to convince you that Clojure is a good idea for Android development. I have no idea how Clojure fairs today, but five-odd years ago a simple hello world would take multiple seconds just to show itself to the user, and the freshest page on Clojure android development said "we looked at this a year ago and it fucking sucked. Nothing to report since!"

Pajeet, I know you don't understand this concept, but the reason Westerners outcompete you is because us coders love programming, it's much more than a 9-5 job.


you're supposed to change your code in response to changing requirements, so here's the final answer for day 1 rather than multiple code-duplicating answers:let adv_faggotry s = let digits = String.length s in let digit c = int_of_char c - int_of_char '0' in let same n m = if s.[n] = s.[m] then digit s.[n] else 0 in let rec loop i acc = if i < 0 then acc else let next = (i + digits / 2) mod digits in loop (i - 1) (same i next + acc) in loop (digits - 1) 0


get a throwaway github. it's the best of the bunch.
they fired the safe-space tranny for persistently making real girls uncomfortable

not an argument


Github is free, you don't have to pay a monthly fee.

You have to pay a monthly fee for private repos.

bitbucket changed their icon to a rainbow one (only visible when logged in, oddly) to celebrate some fag shit. It isn't free if you get AIDS, user.

Yeah but otherwise it's free.

I hope this is more to your taste, user.let use_of_toilet s = let digits = match String.length s with n -> n in let digit = function | '0' -> 0 | '1' -> 1 | '2' -> 2 | '3' -> 3 | '4' -> 4 | '5' -> 5 | '6' -> 6 | '7' -> 7 | '8' -> 8 | '9' -> 9 | _ -> failwith "non-digit found in string" in let same n m = match s.[n] with | c when c = s.[m] -> digit s.[n] | _ -> 0 in let rec loop i acc = let next = match (i + digits / 2) mod digits with n -> n in match i with | 0 -> acc | n -> loop (i - 1) (same i next + acc) in loop (digits - 1) 0


i believe the word you're looking for is "parameter", pajeet

it annoys me that this piece of shit rewrite is actually better for not producing bullshit answers:utop # adv_faggotry "hi there";;- : int = 112utop # use_of_toilet "hi there";;Exception: (Failure "non-digit found in string").Raised at file "", line 32, characters 22-33Called from file "", line 44, characters 25-36Called from file "toplevel/", line 180, characters 17-56

Let's see your solution Pajeet. I'll even let you write it it Java. I'm excited to see how you'll utilize XML to configure your reusable components.

do you bitch when the cable company doesn't give you free pay-per-view?



What do you even watch on television? All the programming is for dumb people. I can see it useful if you like to watch the occasional sporting event but still...

>awarding (((yellow stars))) to people
oy vey!

Day 2 is up.

Looking at the solutions on reddit, I was surprised to see so many of them using Rust... but then I suppose that's the typical demographic.

Looking at that it seems people actively compete for time.
I wasn't even aware there is a time component to this. Just thought it was a nice series of challenges.
(also top ranked people apparently use perl/python so rust btfo)

there are A LOT of chinks on the leaderboard

I did the 2015 competition, and from what I saw on reddit, there was a guy who would rush to finish the solutions in under 2 minutes, and he built a cult of personality around him just for doing that... and even invited people to watch streams of him coding. Very gay.

Very gay indeed. Why can't people just do it for free fun?

Oh apparently we can create private leaderboards, so we could have an 8/tech/ one, but I think it's gay and not worth doing so. Plus you guys would discover my reddit name and bully me.


I ugh, don't have an account.

wouldn't you have to stay up until the new challenge goes live? what if you're from some shit country and the new challenge goes live when its 4am for you?
super shitty

It looks like they come out at 0:00 EST, so for people in England (a shit country), they'd have to wake up at 5:00 in the morning to collect magic points.

totally defeats the point of rushing then imo

Yeah. Funny enough the number #10 guy used Mathematica.

His part1 is marginally better than mine, but I think his part2 is a bit of a mess. I did both parts in under 5 mins, so I'm sure I could have reached the leaderboard (top 100) if I had started when the puzzle dropped. However, despite the Apple badge, I am not gay.


I take that back, my part1 is marginally faster.

I haven't seen anyone using Ada yet.

The J solutions are fucked up. I'm not even sure if I'd want to know that language, I might use it for something.

Multithreaded solution:
extern crate num_cpus;extern crate threadpool;use threadpool::ThreadPool;use std::sync::mpsc::channel;fn main() { let input = vec![ vec![ Some(5), Some(1), Some(9), Some(5) ], vec![ Some(7), Some(5), Some(3), None ], vec![ Some(2), Some(4), Some(6), Some(8) ] ]; let nrows = input.len(); let pool = ThreadPool::new(num_cpus::get()); let (tx, rx) = channel::(); for rows in input { let tx = tx.clone(); pool.execute(move || { let mut minmax = None; for x in rows { if let Some(y) = x { if let Some((min, max)) = minmax { if y > max { minmax = Some((min, y)); } else if y < min { minmax = Some((y, max)); } } else { minmax = Some((y, y)); } } } if let Some(r) = minmax { let _ = tx.send(r.1 - r.0); } else { let _ = tx.send(0); } }); } println!("{}", rx.iter().take(nrows).sum::());}

I don't think the input size necessitates threading user

I'm waiting for the Enterprise Java and relational database solution.

Could someone please screenshot part 2?


day 2let checksum_of_matrix m = let rec difference list low high = match list with | [] -> high - low | n :: rest when n < low -> difference rest n high | n :: rest when n > high -> difference rest low n | _ :: rest -> difference rest low high in let checksum acc list = match list with | n :: m :: rest -> acc + difference (m :: rest) n n | _ -> failwith "row too short" in List.fold_left checksum 0 m(* wtf kind of problem is this *)let checksum2_of_matrix m = let rec hasfactor n = function | [] -> None | m :: _ when m > n && 0 = (m mod n) -> Some (m / n) | m :: _ when m < n && 0 = (n mod m) -> Some (n / m) | _ :: rest -> hasfactor n rest in let rec omega_x_squared orig = function | [] -> failwith "no evenly divisible numbers this column" | n :: rest -> match hasfactor n orig with | None -> omega_x_squared orig rest | Some n -> n in List.fold_left (fun acc list -> acc + omega_x_squared list list) 0 mjust a string list list for a 'matrix'

perhaps the most plebbit thing on this board

spotted the butthurt LARPer

It doesn't necessitate dealing with empty cells and rows either...

extern crate itertools;extern crate num_cpus;extern crate threadpool;use itertools::Itertools;use threadpool::ThreadPool;use std::sync::mpsc::channel;fn main() { let input = vec![ vec![ 5, 9, 2, 8 ], vec![ 9, 4, 7, 3 ], vec![ 3, 8, 6, 5 ] ]; let nrows = input.len(); let pool = ThreadPool::new(num_cpus::get()); let (tx, rx) = channel::(); for row in input { let tx = tx.clone(); pool.execute(move || { let pairs = row.iter().combinations(2); for x in pairs { if x[0]%x[1] == 0 { let _ = tx.send(x[0]/x[1]); } else if x[1]%x[0] == 0 { let _ = tx.send(x[1]/x[0]); } } }); } println!("{}", rx.iter().take(nrows).sum::());}

say what you want about the leaderboard but the digimon christmas story isn't bad

Day 2:
Time: 0.034 ms

I didn't want to taint my system with rust just to compare. How about perf? The second day 2 solution, compiled with ocamlopt and run from shell, overhead and all: Performance counter stats for './p': 1,709,370 cycles 1,534,798 instructions # 0.90 insn per cycle 0.000723235 seconds time elapsed

that's run as: sudo perf stat -e cycles -e instructions ./p
I don't use perf much, just copying someone who uses it

I just included the time to show that it runs

There is no hard requirement on performance you LARPfag.


Are you just pretending to be retarded?

i removed loops:
Time: 0.028 ms

shit. you won. i am sooooooo mad now.

he just doesn't want to compare rust against ocaml for no reason
meanwhile:$ time python -c 'print 1'1real 0m0.039suser 0m0.023ssys 0m0.004s
oh no! christmas is ruined!
tbh I'm not thrilled about getting microbenchmarks working yet under ocaml. Fucking Jane Street changed their tool and the only documentation was the blog for the old version.

If there were a hard requirement on performance you would have to submit your solution and it would only be accepted if it met the requirement.
It's my fault though for expecting a rustfag to be smart.

Please quote me where i said that.
Found the triggered anti Rust shill. Post code or kill yourself.

Do I get those numbers when I log in? I bet your code runs in a fraction of that time if you don't parse the numbers from a string.

But the parsing is part of the challenge.

It really isn't.

The only goal is to solve the challenge. If you happen to be a burger you can compete for how fast you solve but that's all.

how is Mr. Excel programmer supposed to take part then? The obvious way for him to start would be to put today's data in a sheet.
of course for comparison purposes if your inputs are all in the program a cheaty enough compiler could reduce it to a single write() syscall of a static buffer to standard out, with zero calculation.

No it is part of the challenge. Read the lore. You were sent into the computer.

that implies the opposite of "you must do parsing". You're inside a computer. You could just be handed a pointer to a data structure for each of the problems so far.

No I receive my input over HTTP.

fucking hell this autism

Don't worry. I am merely pretending to be retarded.

$*{[-] .comb(/\d+/).map(+*).minmax.bounds.reverse}).sum.say
$*{[/] .comb(/\d+/).combinations(2).map({.sort(-*)}).first({$_[0]%%$_[1]})}).sum.say

Removed indexing:

Horrifying indeed. What language is this?

On second thought, is this perl6? It better not be.

yes, it's perl6.

Does it still have worse performance than perl5?

probably. it's abysmal in every other way. the primary outreach strategy of "try to appeal to little girls" (no really) hasn't worked out for it yet.

Yesterdays problem:

It's slow as shit

Holy shit what? Perl is a stinking camel, not a girly butterfly. I'd upload screenshots for you so you don't have to click, but I can't.

The butterfly was perl6's biggest mistake apart from the god awful shit tier performance.
Perl5 is incredibly fast, especially for anything string related but number crunching is not too bad either.
So what's the most cucked language now, HUH?

While these posts are incredibly shitty there are some true aspects to them.
the cycle never ends

Forgot to say that these blogposts are linked on in one of those useless categories on the top.

i kinda like how terse perl6 can be but all this faggotry surrounding the language is unbearable

Hey guys we're not even as performant as a terrible scripting language, but we have really good support for using invisible non-whitespace unicode operators.
... hey, where are you going? I work in marketing! Come back! It's not like 'concise and fast' is an option anyway right? ha ha!

Learn J or K.

PROC difference = ([]INT a)INT: (INT low := max int, hi := 0; FOR i FROM LWB a TO UPB a DO INT x = a[i]; IF x < low THEN low := x FI; IF x > hi THEN hi := x FI OD; hi - low), checksum = ([][]INT a)INT: IF LWB a > UPB a THEN 0 ELSE difference(a[@1][1]) + checksum(a[@1][2:]) FI;printf(($g(0)l$, checksum( ((5,1,9,5), (7,5,3), (2,4,6,8)))))

i'm doing this to learn pony, first day:
use "cli"actor Main new create(env: Env) => let cs = try CommandSpec.leaf("decaptia", "do level 1 of adventofcode", [ OptionSpec.i64("offset", "offset of number to compare to." where short' = 'o', default' = 1) OptionSpec.i64("percent", "offset of a percent of the the seq len. as a floatpoint number." where short' = 'p', default' = 0) ], [ ArgSpec.string_seq("seq", "the captcha sequenc to evaluate") ])? .> add_help()? else env.exitcode(-1) // some kind of coding error return end let cmd = match CommandParser(cs).parse(env.args, env.vars()) | let c: Command => c | let ch: CommandHelp => ch.print_help(env.out) env.exitcode(0) return | let se: SyntaxError => env.out.print(se.string()) env.exitcode(1) return end let seq: String = try cmd.arg("seq").string_seq().apply(0)? else "0" end var sum: ISize = 0 var pos: ISize = 0 let size = seq.size().isize() let percent = cmd.option("percent").i64().isize() let offset = if percent > 0 then ((size * percent)/ 100) else cmd.option("offset").i64().isize() end repeat try let char = seq(pos.usize())? if char == seq(((pos + offset) % size).usize())? then sum = sum + char.isize() + -48 end end pos= pos + 1 until pos >= size end env.out.print("mew") env.out.print(sum.string())

and second day:
use "cli"use "files"use "debug"actor Main var matrix: Array[Array[I32]]= [] let env: Env new create(env': Env) => env= consume env' let cs = try CommandSpec.leaf("decaptia", "do level 2 of adventofcode", [ OptionSpec.string("file", "What file is the input in" where short' = 'f', default' = "./input") OptionSpec.bool("mod", "devide the two numbers that evenly modulo" where short' = 'm', default' = false) ], [ ArgSpec.string_seq("", "leftover arguments") ])? .> add_help()? else env.exitcode(-1) // some kind of coding error return end let cmd = match CommandParser(cs).parse(env.args, env.vars()) | let c: Command => c | let ch: CommandHelp => ch.print_help(env.out) env.exitcode(0) return | let se: SyntaxError => env.out.print(se.string()) env.exitcode(1) return end try let path = FilePath( env.root as AmbientAuth, cmd.option("file").string() )? match OpenFile(path) | let file: File => for line in FileLines(file) do var temp_array: Array[I32] = [] for item in line.string().split().values() do temp_array.push( try item.i32()? else I32(0) end ) end matrix.push(temp_array) end else env.err.print("Error opening file ") end end env.out.print("...") if cmd.option("mod").bool() then env.out.print(mod_matrix().string()) else env.out.print(sum_matrix().string()) end fun mod_matrix() :I32 => var mod: I32= 0 for line in matrix.values() do var pos: USize= 0 let mod' = mod repeat let i = try line(pos)? else I32(0) end var pos' = pos+ 1 repeat let q = try line(pos')? else I32(0) end mod = mod + ( match I32(0) | (i % q) => i / q | (q % i) => q / i else 0 end ) Debug(pos.string() + " " + pos'.string()) //Debug(mod.string() + " " + mod'.string()) until (pos' = pos' + 1) >= line.size() end until (pos = pos + 1) >= line.size() end Debug(mod) end mod fun sum_matrix() :I32 => var sum: I32= 0 for line in matrix.values() do var min = I32.max_value() var max = I32.min_value() for item in line.values() do let temp = item.i32() if temp > max then max = temp end if temp < min then min = temp end end Debug(min.string() + " " + max.string()) sum = sum + (max-min) end sum

Now do it in a real language (like C)

J advantage:
J disadvantage:
K advantage:
K disadvantage:

no data races and no deadlocks?
that's interesting and all...
but the name of the language is pony
nothing good can come of this
also 'else' (without 'if') in that pattern-matching, gross. Somehow it looks a lot like Java.

Today's thing + some miscellaneous machinery to ease future parsing using namespace std;template constexpr bool grab_while(string_view in, string_view& out, size_t& cur, P&& p){ if (cur >= in.size()) return false; size_t start = cur; if (p(in[cur])) do ++cur; while(cur < in.size() && p(in[cur])); out = string_view( + start, cur - start); return true;}template struct split_iter{ constexpr bool operator!=(nullptr_t) { grab_while(in, out, cur, not_fn(p)); return grab_while(in, out, cur, p); } constexpr string_view operator*() const { return out; } constexpr void operator++() const {} string_view in, out; size_t cur; P p;};template struct split_t{ constexpr auto begin() const { return split_iter{sv, string_view(), 0, p}; } constexpr auto end() const { return nullptr; } string_view sv; P p;};template constexpr auto split(string_view sv, P&& p) { return split_t{sv, forward(p)}; }template constexpr auto split(P&& p) { return [p = forward(p)](string_view sv){ return split(sv, p); }; }template struct map_to_iter{ template constexpr bool operator!=(T&& t) { return it != t; } constexpr auto operator*() const { return f(*it); } constexpr void operator++() const { ++it; } Rit it; F f;};template struct map_to_t{ constexpr auto begin() const { return map_to_iter{r.begin(), f}; } constexpr auto end() const { return r.end(); } R r; F f;};template constexpr auto map_to(R&& r, F&& f) { return map_to_t{forward(r), forward(f)}; }template constexpr auto map_to(F&& f) { return [f = forward(f)](auto&& r){ return map_to(forward(r), f); }; }template constexpr auto operator|(A&& a, B&& b) { return forward(b)(forward(a)); }void corruption_checksum1(string input){ auto sum = 0u; for (string_view line : input | split([](char c){ return c != '\n'; })){ auto minv = ~0u, maxv = 0u; for (unsigned int v : line | split([](char c){ return !isspace(c); }) | map_to([](auto w){ return stoul(string(w)); })) minv = min(minv, v), maxv = max(maxv, v); sum += maxv - minv; } cout

Parallelized version of day 2 vector regroup_lines(string_view input){ const size_t n_thr = omp_get_max_threads(); vector groups; groups.reserve(n_thr); const size_t approx_group_sz = input.size() / n_thr; size_t start = 0; for (size_t i = approx_group_sz, j = 0; j < n_thr - 1; start = i, i += approx_group_sz, ++j){ for (; input[i - 1] != '\n'; ++i) ; groups.emplace_back(&input[start], i - start); } groups.emplace_back(&input[start], input.size() - start); return move(groups);}void corruption_checksum1_parallel(string input){ vector subinput = regroup_lines(input); auto sum = 0u; #pragma omp parallel for reduction(+:sum) for (int i = 0; i < omp_get_max_threads(); ++i) for (string_view line : subinput[i] | split([](char c){ return c != '\n'; })){ auto minv = ~0u, maxv = 0u; for (unsigned int v : line | split([](char c){ return !isspace(c); }) | map_to([](auto w){ return stoul(string(w)); })) minv = min(minv, v), maxv = max(maxv, v); sum += maxv - minv; } cout

man. day. day 3. just.
just.let nextoddroot n = let iseven n = 0 = n mod 2 in let root = 1 + int_of_float (sqrt (float n)) in let root' = if iseven root then root + 1 else root in root' * root'let move (x, y) (dx, dy) = (x + dx, y + dy)let turn_left p = match p with | (1, 0) -> (0, -1) | (0, -1) -> (-1, 0) | (-1, 0) -> (0, 1) | (0, 1) -> (1, 0) | _ -> failwith "Invalid delta"let dump_matrix m = let dim = Array.length m - 1 in let width = String.length (string_of_int (Array.get (Array.get m dim) dim)) + 1 in Array.iter (fun row -> Array.iter (Printf.printf "%*d " width) row; print_newline ()) mlet rec drift m (x, y) delta v n = let row = Array.get m y in Array.set row x v; match n with | 0 -> (x,y) | _ -> drift m (move (x,y) delta) delta (v + 1) (n - 1)let spiral n = let dim = int_of_float (sqrt (float (nextoddroot n))) in let n' = dim * dim in let half = dim / 2 in let m = Array.make_matrix dim dim 0 in let rec loop p d v n = if (v + n) > n' then let _ = drift m p d v (n - 1) in m else let p' = drift m p d v n in let d' = turn_left d in let v' = v + n in let p'' = drift m p' d' v' n in loop p'' (turn_left d') (v' + n) (n + 1) in loop (half, half) (1, 0) 1 1let coord_of_int m n = let length = Array.length m in let rec loop row i = let rec loop' j = if j = length then loop (Array.get m (i + 1)) (i + 1) else let n' = Array.get row j in if n = n' then (j, i) else loop' (j + 1) in loop' 0 in loop (Array.get m 0) 0let omgwtf n = let m = spiral n in let origin = Array.length m / 2 in let (x, y) = coord_of_int m n in abs (x - origin) + abs (y - origin)part 2 is the above with a redefinition of drift:let spy_target = ref 0let spy_found = ref falselet looking_for n = spy_found := false; spy_target := nlet sum_of_neighbors m x y = let sum = safe_get m (x - 1) y + safe_get m (x + 1) y + safe_get m x (y - 1) + safe_get m x (y + 1) + safe_get m (x - 1) (y - 1) + safe_get m (x - 1) (y + 1) + safe_get m (x + 1) (y - 1) + safe_get m (x + 1) (y + 1) in (if not !spy_found then if sum > !spy_target then (spy_target := sum; spy_found := true)); if sum = 0 then 1 else sumlet rec drift m (x, y) delta v n = let row = Array.get m y in Array.set row x (sum_of_neighbors m x y); match n with | 0 -> (x,y) | _ -> drift m (move (x,y) delta) delta (v + 1) (n - 1)let wtfbbq n = looking_for n; let _ = spiral n in (!spy_found, !spy_target)

oh and safe_get:let safe_get m x y = try Array.get (Array.get m y) x with Invalid_argument _ -> 0


day 3 in ye olde C++. I'm sure it must be possible to do part 2 while allocating less memory (i.e. in a deque, push back newest values, remove old values from front), but I'm lazy. void spiral_memory1(size_t pos){ if (!--pos) return cout = pos){ size_t lvl = i >> 3, lvl_start = j + 1 - i, lvl_pos = pos - lvl_start, lvl_on_side = lvl_pos % (i >> 2), half_side = i >> 3; int lvl_side_dist = (int)lvl_on_side - half_side + 1; return cout = val) return 3 + (i >> 2); }(), upper_bound_sz2 = upper_bound_sz >> 1; vector grid(upper_bound_sz * upper_bound_sz); auto at = [&](int x, int y){ return upper_bound_sz2 + x + upper_bound_sz * (upper_bound_sz2 + y); }; grid[at(0, 0)] = 1; for (int x = 1, y = 1, side = 2;; ++x, ++y, side += 2){ for (auto [dx, dy] : {pair(0, -1), pair(-1, 0), pair(0, 1), pair(1, 0)}){ int counter = 0; do { x += dx; y += dy; if (size_t newval = (grid[at(x, y)] = [&]{ size_t sum = 0; for (int j = y - 1; j

they're completely unnecessary in JavaScript except to disambiguate 1 common and 1 rare case, but everyone uses them all the time.
why not in Python too? Just because no big names have told you that the interpreter uses a scaaary yet simple and deterministic algorithm?


did it in OCaml 'cause I'm learning it. but this turtle graphics nonsense I'd rather just do in Forth.
looking at reddit, there is an 'elegant' solution in abusing a mathematical property of the spiral, but that just leaves you with some code that's so optimized for the exact solution that you have to throw it away when it's change.
One thing I do like about this contest is that it gives you a problem and then changes it up, just to break hyper-optimized replies like that.
In the real world I've had a manager tell me he doesn't want a third-party component of some complex software to round a float in a certain way and I was like, uh, shit, I'll get back to you. Flexibility matters.

e.g. rustfag:

I'm not proud.
const INPUT: u32 = 123456;fn part1() { let mut s = 1; let mut x = 0; let mut y = 0; let mut dx = 1; let mut dy = 1; 'b: loop { for _ in 0..dx { if s == INPUT { break 'b; } x += dx%2*2-1; s += 1; } dx += 1; for _ in 0..dy { if s == INPUT { break 'b; } y += dy%2*2-1; s += 1; } dy += 1; } println!("{}", (x as i32).abs()+(y as i32).abs());}fn part2() { fn get(x: i32, y: i32) -> u32 { if x == 1 && y == 0 { 1 } else if x == y { if x == 0 { 1 } else if x > 0 { get(x, y-1) + get(x-1, y-1) } else { get(x, y+1) + get(x+1, y+1) } } else if -x == y { if x < 0 { get(x+1, y) + get(x+1, y-1) } else { get(x-1, y) + get(x, y+1) + get(x-1, y+1) } } else if x-1 == -y && y < 0 { get(x-1, y) + get(x-1, y+1) } else if x-1 == -y && y > 0 { get(x+1, y) + get(x+1, y-1) + get(x, y-1) } else if y-1 == x && x < 0 { get(x, y+1) + get(x+1, y+1) + get(x+1, y) } else if x-1 == y && y < 0 { get(x-1, y) + get(x-1, y+1) + get(x, y+1) + get(x+1, y+1) } else if x == y+1 && y > 0 { get(x-1, y) + get(x-1, y-1) + get(x, y-1) } else if x > y.abs() { get(x, y-1) + get(x-1, y+1) + get(x-1, y) + get(x-1, y-1) } else if y >= x.abs() { get(x-1, y-1) + get(x, y-1) + get(x+1, y-1) + get(x+1, y) } else if y.abs() < -x { get(x, y+1) + get(x+1, y+1) + get(x+1, y) + get(x+1, y-1) } else { get(x-1, y) + get(x-1, y+1) + get(x, y+1) + get(x+1, y+1) } } let mut x = 0; let mut y = 0; let mut dx = 1; let mut dy = 1; 'b: loop { for _ in 0..dx { if get(x, y) > INPUT { break 'b; } x += dx%2*2-1; } dx += 1; for _ in 0..dy { if get(x, y) > INPUT { break 'b; } y += dy%2*2-1; } dy += 1; } println!("{}", get(x, y));}fn main() { part1(); part2();}

Damn. I just want to say that this isn't me.

Question about the day1 challenge partA
What should this testcase return?


just change the input here:

I tested a C and a Python version from further up and they both returned 36

well they are wrong

The rust one returns 45 so it works fine but those other anons fucked it up.
confirmed for shit i guess

is there an Holla Forums private leaderboard yet?

ocaml's fine though:utop # sum_faggotry "9919999";;- : int = 45utop # sum_matching 9919999;;- : int = 45

101 is supposed to match the two 1's together, because it's supposed to loop around. C and Python versions don't do that. I guess the single challenge case happened to not use that rule, but one of the examples asked for it.

But the versions in and do and they give the correct output, see
seems to wrap too.

Fucking WEW! Day 3 is absolute cancer. I first wrote some horrible spaghetti code that worked but took a few milliseconds.
So I rewrote it. Part 1 is now O(1). No idea (and no desire to figure out) how to optimize Part 2.
Time: 0.04 ms

it's so lame to post spoilers before the thing officially ended


nodev LARPer spotted
antisage btw

Straight and to the point, gets the job done. Only 'clever' part is exploiting properties of complex numbers.

45 #MeToo

Nigga what the fuck? How are complex numbers even remotely necessary here?

To keep track of both the position and direction, the real and imaginary parts are the x and y coordinates respectively. So -1,-2i is left once, and down twice.

What makes them nice for this (instead of a vector) is that multiplication by i is a right angle rotation.

Yeah I know that. But why are you using complex numbers for this specifically? It is retarded overengineering.
All you need to do is rotate a 2d vector by 90 degrees. If you can't figure out how to do this without complex numbers you should kys.

That word doesn't mean what you think it does. They're equivalent.

This is quite bad because I am sure you're doing it in floating point and converting back and forth burns CPU and may give inaccurate results once numbers grow big enough

it could be useful in code golf though

It isn't floating point, it is using exact numbers. There is no converting back/forth until the end, and even that is done exactly.

Being a symbolic language, mathematica operates a bit differently in being as general as possible, so even something like (+) could be used to do arithmetic with photos of arbitrary symbols, generality carries a performance penalty. For performance sensitive operations, you can Compile blocks of code to optimize for a specific type. For these day 3 cases, both completed in mere milliseconds.

Of course.

Wew, didn't think HashMaps were fast. My recursive solution for day 3 part 2 takes 30ms minimum.

New solution in Bash:
INPUT=1337; for row in `wget -q -O- | grep -v "^#" | cut -f2 -d' '`; do if [ $row -gt $INPUT ]; then echo $row; break; fi; done

Part 3 converges to a solution really quickly though, those numbers add up very fast. My one completed in under a millisecond.

forgot that it's mathematica
Stallman does not approve it

Day 3 is just straight up a math problem not a programming problem.

Here is your goldstar, you earned it champ

c++ was a mistake

Why, because I showed a bunch of library-ish things that would normally be hidden behind a header file? It makes the actual important code (the "corruption_checksum" functions) look better than if I did parsing manually and more efficient than if I used stringstreams, and that's all that matters.

Not that I would mind having a more elegant way to do these sorts of range transformations, but hopefully coroutines and view adaptors will fix that when they get in C++20.

day 4. Easy enough. void high_entropy_passphrases1(string input){ size_t valid = 0; for (string_view phrase : input | split([](char c){ return c != '\n'; })){ unordered_set words; for (string_view word : phrase | split([](char c){ return !isspace(c); })) if (auto it = words.find(word); it != words.end()) goto next_phrase; else words.insert(word); ++valid; next_phrase:; } cout

let sorted_array_of_string s = let len = String.length s in let a = Array.make len ' ' in for i = 0 to len - 1 do a.(i) if a = b then 0 else if a > b then 1 else -1) a; alet valid_passphrase s = let seen = Hashtbl.create 10 in let rec loop list = match list with | [] -> true | w :: rest -> match Hashtbl.find_opt seen w with | None -> Hashtbl.add seen w (); loop rest | (Some _) -> false in loop ( sorted_array_of_string (String.split_on_char ' ' s))let valid_passphrases () = List.fold_left (fun count phrase -> if valid_passphrase phrase then count + 1 else count) 0 (String.split_on_char '\n' passphrases)part 1 is just this without the (storing strings instead of sorted arrays of char). 'passphrases' is just a copy&paste of the phrases from the website, in a string
feels like the language is missing a Bytes.sort , though it's a pretty rare thing to want, and more obviously a string_to_array which I had to do manually here.

Day 4 is pure cancer. It's completely trivial and after I do both stars it in hurry, I see that another 300 people also got up early and did it faster.
I hoped for problems which, at least, require some thinking. Like day 3 at the very least.

too much typing

import rews = re.compile(r'\s+')def parse_row(l): return tuple(filter(None, ws.split(l)))with open('input.txt', 'r') as f: lines = tuple(filter(None, map(parse_row, f)))i = 0for l in lines: l = tuple(map(lambda x: ''.join(x), map(sorted, l))) h = set(l) if len(h) == len(l): i += 1print(i)

the leaderboard system is designed to suck.
just collect your yellow stars m8

If I recall the previous years, things do get harder later.


well, then day 4 should have been harder than 3.
maybe it's just one error, I dunno.

valid_passphrase exits early with false on the first repeat. It could also exit early without doing sorted_array_of_string to, at the cost of being a little bit longer. explicit tail-recursive loops are more verbose but more flexible than higher-order functions (news at 11).
it's true that sorted_array_of_string adds a lot of length that I already said a better stdlib shouldn't need (anyone doing adventofcode with Core?)
btw python4 in 2019 will break the entire language because Guido will think by then that 'return' should have mandatory parentheses.

optimization is not needed here though
and when it's needed, Rust > Haskell :)

... good on you for not even knowing what Haskell looks like
it's OCaml. It's a language you can use for throwaway scripts and also for serious if-this-breaks-I-am-not-even-fired-because-my-employers-are-out-of-business projects. It has a very large 'dynamic range' according to Jane Street devs so instead of saying "I'll do this unimportant thing in Python and then rewrite it in Rust" you can just say "I'll do this in OCaml".

Haskell, from redditvalid pass = length (nub $ sort pass) == length passmain = interact $ (++"\n") . show . length . filter valid . map words . linespart 2:valid pass = length (nub $ sort $ map sort pass) == length passI'd rather deal with golfed perl. Just disgusting.

Here's someone doing it with Core (alternate stdlib for OCaml):open Corelet all_unique_words words = let set = String.Set.of_list words in String.Set.length set = List.length wordslet sort_chars word = String.to_list word |> List.sort |> String.of_char_listlet sort_words words = words ~f:sort_charslet no_anagrams = Fn.compose all_unique_words sort_wordslet solve () = let split_words = String.split ~on:' ' in let passphrases = In_channel.read_lines "./2017/data/4.txt" |> ~f:split_words in List.filter passphrases ~f:all_unique_words |> List.length |> printf "a: %d\n"; List.filter passphrases ~f:no_anagrams |> List.length |> printf "b: %d\n";

Mathematica makes short work of it.

It can even be golfed shorter, this guy on reddit did it even nicer, hiding my explicit 'True'.

oh yeah, it's the point-less style

fug, of course it's somethingML.
they look very similar when I haven't written in neither of them for a year.

I'm the semicolon python fag, got this for day 3:
import sys;n = int(sys.stdin.readline()) - 1;diag = int(n ** 0.5);walk = n - diag * diag;disc = walk % (diag + diag % 2);offset = diag // 2 - abs(disc - diag // 2);print(diag - offset);

explain yourself
trying to smudge your code fingerprint so that you won't get outed as Google Drone #171234 ?

You mean the semicolons? I'm used to C like languages that's all. I'm doing these in python because I already know C pretty well.

fn main() { let instant = std::time::Instant::now(); let (a, b) = INPUT .lines() .filter_map(|l| { let mut set = FastHashSet::default(); if l.split(' ').all(|s| set.insert(s)) { Some(set) } else { None } }) .fold((0, 0), |(a, b), s| { let mut set = FastHashSet::default(); let valid = s.iter() .map(|s| { let mut v = s.as_bytes().to_owned(); v.sort_unstable(); v }) .all(|b| set.insert(b)); (a + 1, if valid { b + 1 } else { b }) }); let d = instant.elapsed(); println!( "Part 1: {}\nPart 2: {}\nTime: {} ms", a, b, (d.as_secs() as f64 + d.subsec_nanos() as f64 / 1000000000.0) * 1000.0 );}
Time: 0.52 ms

that's some tolerable-looking rust you got right there. eyes aren't bleeding at all. Even so:
not really an improvement over the time() as used by the Greeks and Romans in antiquity
if it's the 'default', why do you have to say that?
eyes status: getting a little bit bloodshot
well ha ha who would expect an answer in fractional msecs? that must be super rare and not the most obviously desirable benchmarking number, next to fractional seconds
still, not bad. would work with rather than ritually commit seppuku.

the virgin haskeller


That's hilarious.

Thanks for the code review.


(import (srfi srfi-1) (ice-9 rdelim))(define (valid? str) (let ((lst (sort (string-split str char-set:blank) string

I optimized it:
Time: 0.3 ms
Suck it faggots! Rust is literally the fastest and safest language.

just use Forth. it compiles a lot faster.

It uses linear probing though

oh. yeah I see it now.

module HashSet =struct let hashset_capacity = 32 type 'a hashset = { buckets : (int * 'a) array; hash_fn : 'a -> int; mutable len : int; } let create f x = { buckets = Array.make hashset_capacity (0, x); hash_fn = f; len = 0 } (* unlike rust, infinite loop possible in loop if hash state goes bad *) let insert ht v = assert (ht.len < hashset_capacity); let hash = ht.hash_fn v in let index = hash mod hashset_capacity in let rec loop i = let i' = (index + i) mod hashset_capacity in match ht.buckets.(i') with | (0, _) -> ht.buckets.(i') loop (i + 1) in loop 0 let clear ht x = Array.fill ht.buckets 0 (Array.length ht.buckets) (0, x); ht.len b then 1 else -1) a; Hashtbl.hash alet () = let before = Unix.gettimeofday () in let asis = HashSet.create hash_asis "" in let sorted = HashSet.create hash_sorted "" in let count_asis = ref 0 in let count_sorted = ref 0 in let rec check_asis words = match words with | w :: words' -> if HashSet.insert asis w then check_asis words' | [] -> count_asis := !count_asis + 1 in let rec check_sorted words = match words with | w :: words' -> if HashSet.insert sorted w then check_sorted words' | [] -> count_sorted := !count_sorted + 1 in let rec loop list = match list with | [] -> let after = Unix.gettimeofday () in Printf.printf "Part 1: %d\nPart 2: %d\nTime: %f s\n" !count_asis !count_sorted (after -. before) | phrase :: rest -> HashSet.clear asis ""; HashSet.clear sorted ""; let words = String.split_on_char ' ' phrase in check_asis words; check_sorted words; loop rest in loop passphrasesbuilt and used as:$ ocamlopt -O3 unix.cmxa -o riio$ ./riioPart 1: 337Part 2: 231Time: 0.003408 s
why is it not faster orz
(changed on hash functions because I don't understand them)
(no hash collision because I didn't want to rewrite code to store sorted value after I realized the mistake)

no serious language uses ' for strings

Because Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.

allaha huakbar

#2: I know collisions don't happen and it's a pretty bullshit data structure anyway :)
#1: the infinite loop requires a bug, for it actually happen. I'm just pointing out a subtle difference in implementation, since I'm mirroring the rust code and that part is different. (it's different because I don't actually know if OCaml has a way to escape early from iterative loops).
pajeets speak 'english'.

on this real world toy problem OCaml and Rust both take no time. That's fine with me.

actually yours takes more than 1 ms which means you have failed. read the aoc lore. you only have 1 ms for each challenge.

it takes more than 1ms on my laptop. my laptop can't digitize people.
you know I didn't actually compare rust against ocaml directly? That would require I install rust. I only have 1TB & 256G disks in this thing.

wrong: > fuuuuuuuuuuuuuark>why is it not faster orz
I don't understand.
where is the problem?

can someone help me with my math for the day 3 part one... abstracted it down to about this then got stuck chasing bugs.. again in pony

fun dist_square(stop': USize) :USize => let stop = (consume stop').isize() var len = ISize(1) // i don't have square root.. or powers.. while (len * len) < stop do len = len + 2 end let dif = (len * len) - stop var corner = dif % (len-1) corner = len - if corner < ((len-1)/2) then corner else (corner - (len-1)).abs().isize() end // my output ((len -1)- corner).usize()

Not one person has submitted a prolog solution. Aren't there any men around here?

What are you trying to do here?

in the problem the last number per layer will always be an odd number squared
17 16 15 14 1318 5 4 3 1219 6 1 2 1120 7 8 9 1021 22 23 24 25
the while loop finds the first odd number that when squared is more then the input number.
that number is the length of one side.

the next line calculates how far back from the end of the layer the input is.

corner starts as how far from the corner closest to the end of the layer the number is, but then should be converted to how far from a corner it is.

then the output (last line) should be the length of one side (max length away from the center for that layer) - how far from the corner the number is..

this works for the first few but falls apart somewhere. all of this is using signed integers so subtraction shouldn't cause overflows.. i'm just stuck.. probably been looking at this too long

ended up diagramming the math and still cant figure it out.

i guess i should say shell not layer

passphrase.m:- module passphrase.:- interface.:- import_module list, string.:- type strictness ---> norepeats; no_anagrams.:- pred is_valid(strictness::in, list(string)::in) is semidet.:- implementation.:- use_module set.is_valid(S, L) :- is_valid(S, L, set.init).:- pred is_valid(strictness::in, list(string)::in, set.set(string)::in) is semidet.is_valid(_, [], _).is_valid(norepeats, [H|T], S) :- not set.contains(S, H), is_valid(norepeats, T, set.insert(S, H)).is_valid(no_anagrams, [H|T], S) :- H1 = from_char_list(sort(to_char_list(H))), not set.contains(S, H1), is_valid(no_anagrams, T, set.insert(S, H1)).puzzle.m:- module puzzle.:- interface.:- import_module io.:- pred main(io::di, io::uo) is det.:- implementation.:- import_module string, list, int, passphrase, time.main(!IO) :- time(Start, !IO), read_file_as_string(Res, !IO), ( Res = ok(Input), Phrases = map(split_at_char(' '), filter(notempty, split_at_char('\n', Input))), count(Phrases, A, B), io.format("part 1: %d\npart 2: %d\n", [i(A), i(B)], !IO), time(End, !IO), io.format("Time: %f s\n", [f(difftime(Start, End))], !IO) ; Res = error(_, Err), io.format("this happened: %s :(\n", [s(error_message(Err))], !IO) ).:- pred notempty(string::in) is semidet.notempty(S) :- length(S) > 1.:- pred count(list(list(string))::in, int::out, int::out) is det.count(L, A, B) :- count(L, 0, A, 0, B).:- pred count(list(list(string)), int, int, int, int).:- mode count(in, in, out, in, out) is det.count([], !A, !B).count([H|T], !A, !B) :- ( passphrase.is_valid(norepeats, H) -> !:A = !.A + 1 ; !:A = !.A ), ( passphrase.is_valid(no_anagrams, H) -> !:B = !.B + 1 ; !:B = !.B ), count(T, !A, !B).usage:$ ./puzzle < ../day-3.txt part 1: 337part 2: 231Time: 0.000000 s

Very noice.

check em'

figured part one of day three out.. removed my conditional.. it's "all" math now.
fun dist_square(input': USize) :USize => let input = (consume input').isize() var len = ISize(1) // i don't have square root.. or powers.. while (len * len) < input do len = len + 2 end /* if i could i would: len = floor(sqrt(input)) len = (len % 2) + len + 1 */ let dif = (len * len) - input let corner = ((dif % (len-1)) - ((len-1)/2)).abs().isize() + ((len-1)/2) Debug(input.string() + " " + corner.string())

day 5. it just werks auto by_line = [](char c) { return c != '\n'; };auto to_int = [](string_view sv) { return stoi(string(sv)); };void twisty_trampolines1(string input){ vector jumps; for (int jump : input | split(by_line) | map_to(to_int)) jumps.push_back(jump); size_t njumps = 0; for (size_t i = 0, sz = jumps.size(); i < sz; ++njumps) i += jumps[i]++; cout = 3) --jumps[i]; else ++jumps[i]; i += jump; } cout

how would they check that?

They don't? The theme this year was that you get sucked into a computer at 50ms before Christmas, and if you don't finish helping the computer in 50 ms Christmas is ruined. Each of the 50 tasks takes 1ms and there's 2 each day for 25 days. It's not real.

fucking hell, I was stumped for a good five minutes because I kept interpreting "three or more" as "> 3". I kept looking for alternative interpretations of "offset" instead.let inst_count = ref 0let eval start a = inst_count := 0; let len = Array.length a in let rec loop i = inst_count := !inst_count + 1; let n = a.(i) in let i' = i + n in if i' < 0 || i' >= len then () else begin (* a.(i)

pretty sure pesonal stats weren't there before? --------Part 1-------- --------Part 2--------Day Time Rank Score Time Rank Score 5 00:33:39 1770 0 00:42:03 1733 0 4 00:35:17 1604 0 00:44:28 1445 0 3 02:13:31 1684 0 02:27:53 1105 0 2 04:38:52 4456 0 04:53:07 3803 0 1 22:16:01 18144 0 22:22:10 15086 0
so nearly 10 minutes due to >= not being >
it was such a minor code change too

I've already done it here:

Actually it is 25 ms before christmas. You have 1ms for both path parts.

fn main() { let instant = std::time::Instant::now(); let ops: Vec = INPUT.lines().map(|l| l.parse().unwrap()).collect(); let a = execute(&mut ops.clone(), |v| v + 1); let b = execute(&mut ops.clone(), |v| if v >= 3 { v - 1 } else { v + 1 }); let d = instant.elapsed(); println!( "Part 1: {}\nPart 2: {}\nTime: {} ms", a, b, (d.as_secs() as f64 + d.subsec_nanos() as f64 / 1000000000.0) * 1000.0 );}fn execute(ops: &mut [i32], f: fn(i32) -> i32) -> u32 { let mut steps = 0; let mut i = 0; while (i as usize) < ops.len() { let o = &mut ops[i as usize]; i += *o; *o = f(*o); steps += 1; } steps}
Time: 83 ms
I fucking blew it. I ruined Christmas.

I guess all that safety comes at a price :^)


Part1 was straight forward. Side effect heavy loops like my part 2 solution, which spend a lot of time in the language rather than library functions is the bane of performance. After 45 seconds I still didn't have an answer for part2!!! The remedy is to use compiled functions, where simpler code is emitted which makes use of some type assumptions, that yielded a result in 2 seconds. Even more gains can realized by emitting C code. That got it down to 0.5 secs, won't win a speed record, but it'll do. Thanks C!


Pretty substantial drop off from day 2 to 3.

Can you hear that? It's the sound of over 9000 Pajeets vanishing.

day 5 was pretty easy. not a shock like day 3 was. it's probably just Monday night and people having jobs.

Day 5 in Rust:
use std::fs::File;use std::io::{BufReader, BufRead};fn part1(mut jumps: Vec) -> u32 { let len = jumps.len(); let mut i = 0; let mut ctr = 0; while i < len { jumps[i] += 1; i = (i as i32 + jumps[i] - 1) as usize; ctr += 1; } ctr}fn part2(mut jumps: Vec) -> u32 { let len = jumps.len(); let mut i = 0; let mut ctr = 0; while i < len { if jumps[i] >= 3 { jumps[i] -= 1; i = (i as i32 + jumps[i] + 1) as usize; } else { jumps[i] += 1; i = (i as i32 + jumps[i] - 1) as usize; } ctr += 1; } ctr}fn main() { let file = File::open("input").unwrap(); let mut jumps: Vec = vec![]; for line in BufReader::new(file).lines() { jumps.push(line.unwrap().parse::().unwrap()); } println!("{}", part1(jumps.clone())); println!("{}", part2(jumps.clone()));}
Takes about 3 seconds.

Forgot to use --release, now it runs in about 100ms.

Not awful but still pretty bad.
read from stdin and pipe input into it
use Iterator::collect
you already have said that you want i32. no need to use the ugly turbofish syntax.
there is only a minor difference between those. also there is no need to give thos functions a vec. just give them a &mut [i32].
maybe the compiler is smart enough to remove them, but check out slice::get_mut

Take a look at this: use std::io::BufRead;fn main() { let stdin = std::io::stdin(); let ops: Vec = stdin .lock() .lines() .map(|l| l.unwrap().parse().unwrap()) .collect(); let a = execute(&mut ops.clone(), |v| v + 1); let b = execute(&mut ops.clone(), |v| if v >= 3 { v - 1 } else { v + 1 }); println!("{} {}", a, b);}fn execute(ops: &mut [i32], f: fn(i32) -> i32) -> u32 { let mut steps = 0; let mut i = 0; while let Some(o) = ops.get_mut(i as usize) { i += *o; *o = f(*o); steps += 1; } steps}

Thank you for your feedback. I've seen your post but only after I posted my solution.

We both call .clone() on a Vec, which returns a Vec but gets casted (?) to a &mut [i32] without actually changing any data. Or is there any difference?

No there really isn't a difference. I was just nitpicking.

Scrub tier perl solutions for day5
use strict;use warnings "all";my @data;while () { push(@data, $_);}my $size = int @data;my $index = 0;my $jumps = 0;for (;;) { $index += $data[$index]++; ++$jumps; if ($index > $#data) { die "$jumps\n"; }}__DATA__0301-3

use strict;use warnings "all";my @data;while () { push(@data, $_);}my $size = int @data;my $index = 0;my $jumps = 0;for (;;) { $index += $data[$index] >= 3 ? $data[$index]-- : $data[$index]++; ++$jumps; if ($index > $#data) { die "$jumps\n"; }}__DATA__0301-3

Ungolfed Perl6:
my $i = 0;my $res= 0;my $instr =*).Array;while ($i < $instr.elems) { $i += $instr[$i] >= 3 ?? $instr[$i]-- !! $instr[$i]++; $res++;}$res.say
~ $ time perl6 dik.pl6 < input23948711real 1m40.691suser 1m40.647ssys 0m0.037s
Compared to my Rust version thats pretty much the one Steve Klabnik posted:
~ $ time ./dik < input23948711real 0m0.054suser 0m0.051ssys 0m0.003s
Perl6 truly is the future of computing.

[email protected]_,$_ while;$i+=$_[$i]>=3?$_[$i]--:$_[$i]++while$i

rip perl6, we hardly knew ya

>all these implementations that only check for i < arraysize
fug did I imagine that requirement as well?

In my solution i is a signed integer that I cast to an unsigned one. Thanks to the awesomness of two's complement this just werks.

Did almost all of them in python but stuck on puzzle 3. Any hints? pls no spoilers

You either generate the spiral and keep track of two coordinates, or you just work it out with math.

an easy way to do the spiral in python would be to use 2d coordinates as dictionary keys

school... it's finals season so (I) can't code much.
as soon as school is done it's all i'll be doing though.

2016 stats. The dropoff was gradual, but pretty substantial from day 1 to 25. Looks like there's a lot more people doing it this year. I did 2015 at the time, but I'm going back and doing the 2016 ones now as well.

You could also do recursion, like one of the R*st solutions in this thread. Hint: don't.

Kinda unrelated but, I'm thinking of doing a libparseinput (get_next_word, get_next_number etc) and them doing every challenge in C, then release it on github as a portfolio sort of thing. Is this a good idea or should I not bother?

It's certainly not a bad idea, but keep in mind that there are already thousands out there, so make sure it represents your best work.

(define* (read-input #:optional (acc '())) (let ((elem (read))) (if (eof-object? elem) (reverse acc) (read-input (cons elem acc)))))(define* (count-jumps array #:optional (part 1) (idx 0) (count 1)) (let* ((value (array-ref array idx)) (new-idx (+ idx value)) (inc (if (and (= part 2) (>= value 3)) 1- 1+))) (if (array-in-bounds? array new-idx) (begin (array-set! array (inc value) idx) (count-jumps array part new-idx (1+ count))) count)))(let ((input (read-input))) (format #t "~A\n~A\n" (count-jumps (list->array 1 input) 1) (count-jumps (list->array 1 input) 2)))

What language is this?

And done for day 6. bool by_word(char c) { return !isspace(c); }void memory_reallocation1(string input){ string mem; for (int val : input | split(by_word) | map_to(to_int)) mem.push_back(val); unordered_set seen; size_t ncycles = 0; for (; !seen.count(mem); ++ncycles){ seen.insert(mem); auto it = max_element(mem.begin(), mem.end()); int redist = *it; *it = 0; for (size_t sz = mem.size(), i = (it - mem.begin() + 1) % sz; redist; ++i %= sz){ ++mem[i]; --redist; } } cout

are you retarded

wtf does part 2 of day 6 even mean?

god fucking damnit it's asking the same exact question again and expecting a different answer.

close, but not exactly

ugh ok. 2nd question says "you see X again after 4 cycles so the answer is 4". 4 is also the answer when you put X itself into your block-reallocation function, but what they mean is "given the input from the first example the repeat that ends the sequence is seen again 4 cycles after the first time it was seen"

let smooth_from a i = let len = Array.length a in let blocks = a.(i) in let to_each = int_of_float (floor (0.5 +. (float blocks /. float len))) in a.(i) string_of_int n :: acc) [] a) in let steps = ref 0 in while None = (Hashtbl.find_opt seen (wtf a)) do Hashtbl.add seen (wtf a) !steps; smooth_from a (max_block a); steps := !steps + 1 done; (!steps, !steps - Hashtbl.find seen (wtf a), a)1. the 'wtf' function is of course a wtf; I should have a real hash function for the array and use that instead.
2. the max block should probably be tracked while reallocating, so that it doesn't have to be looked up again
3. with the input as small as they are one option would be to use Bytes (a mutable string) instead of an array of ints. that gets rid of the wtf function

(define (redist! lst) (define (circ-cdr lst cur) (if (pair? (cdr cur)) (cdr cur) lst)) (let* ((max-blocks (apply max lst)) (max-pair (memq max-blocks lst))) (set-car! max-pair 0) (let loop ((current-pair (circ-cdr lst max-pair)) (blocks-left max-blocks)) (if (> blocks-left 0) (begin (set-car! current-pair (1+ (car current-pair))) (loop (circ-cdr lst current-pair) (1- blocks-left)))))))(define* (read-input #:optional (acc '())) (let ((elem (read))) (if (eof-object? elem) (reverse acc) (read-input (cons elem acc)))))(let loop ((lst (read-input)) (htable (make-hash-table)) (count 1)) (hash-set! htable (list-copy lst) count) (redist! lst) (let ((value (hash-ref htable lst))) (if value (format #t "~A\n~A\n" count (- count value -1)) (loop lst htable (1+ count)))))

Day 6 (cleaned up a bit)

What happens if day 6 part 1's input is [2, 0, 0, 0]? To evenly distribute 2 over 3 fields, each must get 0, so the first field gets 2 back. Right?

nevermind, I misunderstood the question

Day 6 in Rust:
const NUM_MEMBANKS: usize = 4;fn main() { let input = [0, 2, 7, 0]; let mut ctr = 0; let mut history = vec![input]; let size; loop { ctr += 1; let largest = history.last().unwrap().iter().enumerate().fold( (0, 0), |acc, x| { if *x.1 > acc.1 { (x.0, *x.1) } else { acc } } ); let mut i = (largest.0 + 1)%NUM_MEMBANKS; let mut new = *history.last().unwrap(); new[largest.0] = 0; for _ in 0..largest.1 { new[i] += 1; i = (i + 1)%NUM_MEMBANKS; } if history.contains(&new) { size = history.iter().position(|&x| x == new).unwrap(); break; } else { history.push(new); } } println!("Part 1: {}", ctr); println!("Part 2: {}", ctr-size);}
So today I learned Rust has no sizeof(). uses .len() on a literal array

You're right. While I was writing my solution I had a different approach in mind where I had to pass the input array to a function. I could have either passed a reference, which wasn't what I wanted, or I could have specified the array's size in the function declaration, where .len() doesn't work.

Like this:
const arr: [u32; 3] = [1,2,3];fn test(x: [u32; arr.len()]) { println!("{:?}", x);}fn main() { test(arr);}

less wtf:let max_block b = let max, maxi = ref (Bytes.unsafe_get b 0), ref 0 in Bytes.iteri (fun i c -> if c > !max then (max := c; maxi := i)) b; !maxilet balance2 b = let hash x = Hashtbl.hash x in let len = Bytes.length b in let seen = Hashtbl.create len in let get i = int_of_char (Bytes.unsafe_get b i) in let set i n = Bytes.unsafe_set b i (char_of_int n) in let reallocate i = let blocks = get i in let to_each = int_of_float (floor (0.5 +. (float blocks /. float len))) in set i 0; let rec loop j rest = set j (get j + (max 0 (min to_each rest))); if rest < 0 || i = j then () else loop ((j + 1) mod len) (rest - to_each) in loop ((i + 1) mod len) blocks in let rec loop = function | None -> Hashtbl.add seen (hash b) (Hashtbl.length seen); reallocate (max_block b); loop (Hashtbl.find_opt seen (hash b)) | Some last -> (Hashtbl.length seen, Hashtbl.length seen - last) in loop None

rare instance found of actually readable Haskell
naturally the author posted it with a sincere apology. that community is fuckedimport Data.Sequence (Seq)import qualified Data.Sequence as Seqimport Data.Set (Set)import qualified Data.Set as Setimport Data.Listdistribute :: Int -> Int -> Seq Int -> Seq Intdistribute 0 _ banks = banksdistribute remaining currentIndex banks = distribute newRemaining newIndex newBanks where newRemaining = remaining - 1 newIndex = mod (currentIndex + 1) (length banks) newBanks = Seq.adjust (+1) currentIndex banksdoCycle :: Seq Int -> Seq IntdoCycle banks = distribute largestBank startIndex withoutLargest where largestBank = maximum banks bankIndex = head $ Seq.elemIndicesL largestBank banks startIndex = mod (bankIndex + 1) (length banks) withoutLargest = Seq.update bankIndex 0 banksgetFirstRepeatedConfig :: Int -> Seq Int -> Set (Seq Int) -> (Int, Seq Int)getFirstRepeatedConfig count banks prevConfigs | Set.member banks prevConfigs = (count, banks) | otherwise = getFirstRepeatedConfig newCount newBanks newPrevConfigs where newCount = count + 1 newBanks = doCycle banks newPrevConfigs = Set.insert banks prevConfigsgetTimeToCycle :: Int -> Seq Int -> Seq Int -> IntgetTimeToCycle count banks targetConfig | banks == targetConfig = count | otherwise = getTimeToCycle newCount newBanks targetConfig where newCount = count + 1 newBanks = doCycle banksmain :: IO ()main = do contents

(((functional programming)))

perl is perlfect for challenges because it lets you do anything even if its retarded beyond belief

How the FUCK are you supposed to do days 5 and 6 in under 1ms?????????????????
What the FUUUCK. I just can't get day 6 below 1.2ms.

You don't need to????

I want to!

Take your autism and leave


How did you do day 6 in 1.2ms?
I'd store already visited values in a stack allocated binary tree and use SIMD instructions for adding the numbers. I'll try that later when I'm home again and if I'm not too drunk.

too slow
llvm already does that for me

Treat the puzzle input as the real world application that you're optimizing for. Look for useful properties.
1. Small array: 16 elements
Small numbers: each fits in a nibble (4 bits, one hexadecimal digit)
4 * 16 = 64 bits. sound familiar?
2. if each number you look at fits in 4 bits, you will always do one of at most 16 possible things to the rest of the array. Depending also on the index of the number you're looking at, so 16*16=256 possible things based on index and number at that index.
3. Maybe there are useful patterns within the 256 total manipulations.

FUUUUUUUUUUCK! Christmas is ruined again.
Time: 1.15 ms

Hmm if I run it 1000 times and take the average time it is

You've got 25 ms total though, so as long as your averaging under 1ms you'll be fine. You should link all your solutions together and see if it they collectively run under 25 (6 for now) ms.

Every day except 5 runs under 1ms. Day 5 takes 83 ms:
I'm doing that. Right now it is a mess though. Once I've cleaned it up I'll make a ShitHub repo.

Ahh, day 5 is going to make it rather untenable then. And who knows what length solutions lie ahead.

/** * Copyright m712 2017. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see>. */#include #include #include #include struct pos { int item, index;};voidprint_banks(int *banks, int blen) { printf("["); for (int i = 0; i < blen; i++) printf("%d, ", banks[i]); printf("\b\b] \n");}intnext_int() { int val = 0; char c; while (isdigit((c = getchar()))) { val *= 10; val += c - '0'; } if ((int) c == EOF) return EOF; else if (!isspace(c)) { fprintf(stderr, "Not a number"); abort(); } return val;}voidpush_to_banks(int **banks, int *blen, int val) { int len = *blen; if (len % 8 == 0) *banks = realloc(*banks, (len+8) * sizeof(int)); int *rbanks = *banks; rbanks[len] = val; *blen = len+1;}voidpush_to_steps(int ***steps, int *slen, int *banks, int blen) { int len = *slen; if (len % 8 == 0) *steps = realloc(*steps, (len+8) * sizeof(int *)); int **rsteps = *steps; int *newbanks = malloc(blen * sizeof(int)); memmove(newbanks, banks, blen * sizeof(int)); rsteps[len] = newbanks; *slen = len+1;}intsteps_index(int **steps, int slen, int *banks, int blen) { int i = 0, j; int *step;start: while (i < slen) { step = steps[i]; for (j = 0; j < blen; j++) { if (step[j] != banks[j]) { i++; goto start; } } return i; } return -1;}struct pospop_max(int *banks, int blen) { int i, max = 0, mi = 0; for (i = 0; i < blen; i++) { if (banks[i] > max) { max = banks[i]; mi = i; } } banks[mi] = 0; return (struct pos) {max, mi};}intmain(int argc, char **argv) { int *banks = NULL; int **steps = NULL; int blen = 0, slen = 0; int part; if (argc != 2 || ((part = (*argv[1])-'0') != 1 && part != 2)) { fprintf(stderr, "Usage: %s [part:1|2]\n", argv[0]); return 1; } int val; while ((val = next_int()) != EOF) push_to_banks(&banks, &blen, val); int repeat; while((repeat = steps_index(steps, slen, banks, blen)) == -1) { print_banks(banks, blen); push_to_steps(&steps, &slen, banks, blen); struct pos pos = pop_max(banks, blen); for (int i = 1; i /dev/nullTotal steps: 4074real 0m0.044suser 0m0.041ssys 0m0.002s
Christmas is fucked beyond comprehension. Most of the slowness is due to steps_index, which can be fixed by implementing a hashmap. I'll bother with it tomorrow.

why is this so fucking verbose? not even my optimized rust version that implements its own hashmap is this fucking long.
is your blazechan code also this shit?

It's perfectly normal C.
Stylistically, C is all downhill from here, especially as it's ported.

C doesn't have that big of an stdlib, therefore you need to imperatively do some stuff.
I read ints from stdin and parse it, while your input is embedded. Plus your parsing is one chain statement whereas mine is 10 lines because no stdlib support (don't really want to use scanf).
Your program is limited to 128 bytes while mine is generic and its limits are your computer's RAM limits.
Out of 12K LOC incl. JS+CSS+HTML, Blazechan is about 5.5K LOC python, 80% of which is SLOC.

Brain melt, i meant 16 ints.

Then stop using C tbh
Changing it to read from stdin wouldn't change the LOC of my Rust solution.
The challenge states that there are only 16 memory banks

I rate you pajeet/10

no u
Selectively replying to a statement won't gain you an argument. You use a chain function to parse the input line, which is simpler than the C solution I did. Perhaps I phrased it wrong.
Yes, and? I made my program to take any amount of memory banks. Your solution isn't scalable while mine is. This matters in real world development which these series of code challenges are trying to educate you about.
I rate you "not an argument"/10.

polite bump

This is a fucking challenge. Holy shit stop LARPing.

Keep that mindset, Pajeet. How's that stackoverflow copy&paste job going? Get back to work.

Some people take this way too serious. It's just a bunch of puzzles that you solve for fun. All the top rated guys don't give two shits about performance as long as their code is done first.

How am I the pajeet though? You wrote the slow and bloated mess, that does more than it is required to do because "real world development".
It isn't meant to "educate" about "real world development". It is meant to be a fun little challenge every day until christmas.

Actually no, depending on input it runs well below 1ms:
#include #include #include #include #include const unsigned char INPUT[] = {0, 1, 2, 3, 2, 1, 4, 5, 6, 7, 10, 11, 12, 13, 14, 10};struct tree { unsigned char data[16]; struct tree *left; struct tree *right; unsigned int step;};inline char cmp128(__int128 a, __int128 b){ if (a > b) { return 1; } else if (a < b) { return -1; } else { return 0; }}int main(){ struct timeval start; struct timeval end; gettimeofday(&start, NULL); struct tree history; memcpy(, INPUT, 16); history.left = NULL; history.right = NULL; history.step = 0; unsigned int ctr = 0; unsigned int size; unsigned char *curdata =; for (;;) { ctr++; struct tree *new = alloca(sizeof(struct tree)); memcpy(new->data, curdata, 16); new->left = NULL; new->right = NULL; new->step = ctr; curdata = new->data; unsigned char max_c = 0; unsigned char max_v = 0; for (unsigned char i = 0; i < 16; i++) { if (new->data[i] > max_v) { max_c = i; max_v = new->data[i]; } } new->data[max_c] = 0; for (unsigned char i = 0; i < 16; i++) { new->data[i] += max_v/16; } for (unsigned char i = 0; i < max_v%16; i++) { new->data[(i+max_c+1)%16]++; } struct tree *ptr = &history; for (;;) { char cmp = cmp128(*((__int128 *) ptr->data), *((__int128 *) new->data)); if (cmp > 0) { if (ptr->left == NULL) { ptr->left = new; break; } else { ptr = ptr->left; } } else if (cmp < 0) { if (ptr->right == NULL) { ptr->right = new; break; } else { ptr = ptr->right; } } else { size = ctr-ptr->step; goto b; } } }b: gettimeofday(&end, NULL); printf("Part 1: %d\nPart 2: %d\n", ctr, size); printf("Time: %ld us\n", (end.tv_sec-start.tv_sec)*1000000+end.tv_usec-start.tv_usec); return 0;}

Yeah try my input: 4, 10, 4, 1, 8, 4, 9, 14, 5, 1, 14, 15, 0, 15, 3, 5
Your solution takes 7ms with it.

On my machine:
But yeah it's not optimal. With the input from it runs in 1.2ms, with some guy's numbers I found on reddit (0, 14, 13, 12, 11, 10, 8, 8, 6, 6, 5, 3, 3, 2, 1, 10) it's 0.3ms.

The top rated guys are complete faggots who are too serious about the contest part of the contest, even when it has a design that's blatantly hostile to competition. The discussion you're objecting to is actually productive and beneficial beyond the competition.

You could try a bloom filter.

Finally day 7 required a bit of thinking to get through.
Still, it's mostly brute force.

import refrom collections import defaultdictpt = re.compile(r'(\w+) \(([0-9]+)\)(?: -> (.*))?\n?')def parse_row(l): m = pt.fullmatch(l) bottom, bottom_weight, *r = m.groups() other = r[0].split(', ') if r and r[0] else () return bottom, bottom_weight, otherall = set()not_bottom = set()class P: def __init__(self): = None self.weight = None self.parent = None self.children = Noneall_linked = defaultdict(P)with open('input.txt', 'r') as f: lines = map(parse_row, f) for bottom, w, other in lines: bp: P = all_linked[bottom] = bottom bp.weight = int(w) bp.children = tuple(map(lambda x: all_linked[x], other)) all.add(bottom) not_bottom.update(other)root = all_linked[next((all - not_bottom).__iter__())]print( calc_weight(root: P): return root.weight + sum(map(calc_weight, root.children))def check_weight(root: P): diff = 0 while True: weights = tuple(map(calc_weight, root.children)) hst = defaultdict(int) for w in weights: hst[w] += 1 hst = tuple(hst.items()) if len(hst) > 1: wrong_weight = next(filter(lambda x: x[1] == 1, hst))[0] correct_weight = next(filter(lambda x: x[1] != 1, hst))[0] wrong_tree_index = next(i for i in range(len(weights)) if weights[i] == wrong_weight) wrong_tree = root.children[wrong_tree_index] diff = correct_weight - wrong_weight root = wrong_tree else: return root.weight + diffprint(check_weight(root))

total weight could be cached to avoid recalculating it but I didn't bother because it gives answer in a fraction of a second anyway.

day 7. phew. void recursive_circus1(string input){ unordered_set has_base, has_no_base; for (string_view line : input | split(by_line)){ auto [name, rest] = grab_while(line, by_alpha); if (!has_base.count(name)) has_no_base.insert(name); for (string_view supported : rest | split(by_alpha)){ if (auto it = has_no_base.find(supported); it != has_no_base.end()) has_no_base.erase(it); has_base.insert(supported); } } cout total_weight = parent->weight; for (node_t* child : parent->next){ if (int nw = needed_weight(child); nw != ~0u) return nw; parent->total_weight += child->total_weight; } if (parent->next.size() > 2){ auto majority = [&](auto&& f){ return f(0) == f(1) || f(0) == f(2) ? f(0) : f(1); }; int majority_total_weight = majority([&](size_t i){ return parent->next[i]->total_weight; }); for (node_t* child : parent->next){ if (child->total_weight != majority_total_weight) return child->weight - child->total_weight + majority_total_weight; } } return ~0u;}void recursive_circus2(string input){ unordered_map tree; unordered_set has_base, has_no_base; for (string_view line : input | split(by_line)){ auto [name, rest1] = grab_while(line, by_alpha); auto [ignored, rest2] = grab_while(rest1, not_fn(by_num)); auto [weight, rest] = grab_while(rest2, by_num); node_t& node = tree[name]; node.weight = stoi(string(weight)); vector& next =; if (!has_base.count(name)) has_no_base.insert(name); for (string_view supported : rest | split(by_alpha)){ if (auto it = has_no_base.find(supported); it != has_no_base.end()) has_no_base.erase(it); has_base.insert(supported); next.push_back(&tree[supported]); } } cout

is it C++18? or what version?
last time I saw any C++ code it didn't look like that.

days 1-6: avg 10 min to answer second question
day 7: one hour to answer second question
code is complete shit too. I just didn't want to do this one proper. no ocaml today:utop # (fun x -> total_weight [x]) (Hashtbl.find claims "tdxow");;- : int list list = [[1184]; [1184]; [1192]]utop # Hashtbl.find claims "tdxow";;- : string list = ["mrxqlw"; "htzrkz"; "ghwgd"]utop # (fun x -> total_weight [x]) (Hashtbl.find claims "ghwgd");;- : int list list = [[274]; [274]; [274]]utop # Hashtbl.find names "ghwgd";;- : int = 370utop # 274 * 3 + 370;;- : int = 1192utop # 1184 - 274 * 3;;- : int = 362

I'm using C++17.
"std::string_view", "std::not_fn", the "auto [name, rest1] = grab_while(line, by_alpha);" return value decomposition thing and the ability to declare a variable inside the if clause are C++17 features. Lambdas are a C++11 feature (or C++14 when the arguments are generic), and so are "auto" and range-based for loops. Function return type deduction (with auto) is a C++14 feature. The whole "input | split(by_line)" hack comes from the ugly pile of class templates I defined here: (also exploits some C++17 features, like how begin() and end() don't have to be the same type in a range-based for loop) (some corrections have been made since I wrote it).

I'm probably forgetting something.

hmmmm that looks interesting.
then how would you write the solution if you were not allowed to use templates beyond simple parametric polymorphism (like in Java or Haskell)?

and in general is C++ worth learning now that it got all this cool stuff? especially with regard to difficulty of writing code that doesn't corrupt memory.
or I'd better create a designated thread for the discussion of modern C++?

Mathematica Day 7. The stack weight is being amortized, but that's not necessary as the tree (at least in my input) isn't very deep.

Everything here is parametric polymorphism + function/operator overloading, though. I'm not using any template specialization or weird metaprogramming tricks (i.e. "SFINAE") here. In the newest version of , I'm using a type trait in one place, but that's it. If you mean without any of at all, I might do something like this (untested): for (string_view line, rest = input; tie(line, rest) = grab_while(rest, by_line), !line.empty();){ //do other transformations on line here //...} ("tie" is a standard library function).
I think so, though it's a lot to learn. And in C++20 a lot more useful things are going to be added, like coroutines, modules, concepts, networking (I think) and possibly some basic reflection.
Depending on what you do, you may still have to be careful (for instance, in recursive_circus2 I'm storing node_t* pointers to elements inside an unordered_map, then adding new elements with "tree[name]", which is only correct because calling unordered_map's operator[] doesn't invalidate references; if for example I was pushing those nodes into a vector instead, I couldn't have done that). Still, I think modern C++ is a lot better than C or old C++ in that regard (e.g. memory leaks are easy to avoid using std::unique_ptr, string buffer overflows/corruption are easy to avoid with std::string and std::string_view, etc.).
If this conversation gets too large, I guess.

Day 7 has only been available for 3 hours 20 mins, so this'll certainly grow, but that's still quite small compared to other days by this time. Also notice that there's quite a lot of Part A people here, showing that Part B is proving to be a stumbling block for many.
(reposting with image)

#!/usr/bin/env python3# Copyright m712 2017.## This program is free software: you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation, either version 3 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program. If not, see>.import sysimport reimport collectionsclass Tree(object): def __init__(self, name, weight, children): = name self.weight = weight self.children = children self.parent = None def __repr__(self): return "".format(type(self).__name__, str(self)) def __str__(self): return "{:s} ({:d}) -> {:d} children".format(, self.weight, len(self.children))def parse(input): trees = {} for line in filter(lambda x: x, input.split('\n')): # name (weight) -> a, b, c words = line.split(' ', 3) name, weight, children = (words[0], int(re.sub(r'\((\d+)\)', r'\1', words[1])), [] if len(words) < 3 else list(map(str, words[3].split(', ')))) trees[name] = Tree(name, weight, children) for t in trees.values(): t.children = list(map(lambda x: trees[x], t.children)) for c in t.children: c.parent = t return list(trees.values())def part1(trees): def climb(tree): if not tree.parent: # at the top return tree else: return climb(tree.parent) return climb(trees[0])def total_weight(tree): return tree.weight + sum(map(total_weight, tree.children))def average(tree): return (tree.total_weight - tree.weight) // len(tree.children)def calc_weights(tree): tree.total_weight = total_weight(tree) for t in tree.children: calc_weights(t)def part2(tree): calc_weights(tree) parent = tree diff = None while True: commons = collections.Counter(t.total_weight for t in parent.children ).most_common() print(parent, commons, diff) if len(commons) == 1: return parent.weight - diff diff = commons[1][0] - commons[0][0] parent = list(filter(lambda t: t.total_weight == commons[1][0], parent.children))[0]if __name__ == "__main__": print('Enter tree:') trees = parse( print('Top of tree:', part1(trees).name) print('Correct value:', part2(part1(trees)))
[email protected]:~$ time python3 /dev/nullreal 0m0.095suser 0m0.072ssys 0m0.008s
C version coming after the Py3 implementation.

Pajeets having trouble traversing a tree

Ugh I meant memoized

They're just waiting for the Java solution to be posted on reddit so they can copy+paste into Eclipse.

/** * Copyright m712 2017. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see>. */#include #include #include #include #include typedef struct _node { char *name; __uint128_t hash; int weight, total_weight; struct _node **children; int clen; char **raw_children; int rlen; struct _node *parent;} Node;#define GROW_CHUNK 8#define CHECK_SIZE(type, arr, len) \ do { \ if ((len) % GROW_CHUNK == 0) \ (arr) = realloc((arr), \ ((len)+GROW_CHUNK) * sizeof(type)); \ } while (0)#define PUSH(type, arr, len, item) \ do { \ CHECK_SIZE(type, arr, len); \ (arr)[len] = (item); \ (len)++; \ } while (0)#define DESTROY(arr, len, i) \ do { \ for (i = 0; i < len; i++) \ free(arr[i]); \ free(arr); \ } while (0)#define EXPLODE(str, ...) \ do { \ printf("\033[0m" str "\n", __VA_ARGS__); \ abort(); \ } while (0)/** * a-z = 27 combinations. * This hash implementation supports up to 25 characters + 4 lower bits. * Case-insensitive */#define HASH(str, hash) \ do { \ int len = strlen(str); \ for (int hi = 0; hi < len; hi++) \ hash |= ((__uint128_t) ((tolower(str[hi]) - 'a') & 0x1F)) \ children, Node *node = calloc(1, sizeof(Node)); CHECK_SIZE(char **, node->raw_children, 0); int c; node->name = get_word(); HASH(node->name, node->hash); getchar(); // space c = getchar(); // ( if (c != '(') EXPLODE("Expected ( at line %d", line); node->weight = get_int(); getchar(); // ) c = getchar(); // " ->" or \n or EOF if (c == '\n' || c == EOF) { CHECK_SIZE(Node *, node->children, 0); // initialize return node; } else if (c != ' ' || getchar() != '-' || getchar() != '>') EXPLODE("Expected -> or newline at line %d", line); getchar(); // space for (;;) { PUSH(char **, node->raw_children, node->rlen, get_word()); c = getchar(); // \n or EOF or ", " if (c == '\n' || c == EOF) { return node; } else if (c != ',' || getchar() != ' ') EXPLODE("', ' or newline expected at line %d", line); }}Node *find_node(Node **nodes, int len, const char *name) { __uint128_t hash = 0; HASH(name, hash); for (int i = 0; i < len; i++) if (nodes[i]->hash == hash) return nodes[i]; return NULL;}

voidresolve_tree(Node **nodes, int len) { for (int i = 0; i < len; i++) { Node *node = nodes[i]; for (int j = 0; j < node->rlen; j++) { Node *child = find_node(nodes, len, node->raw_children[j]); if (!child) EXPLODE("Node '%s' references unknown child '%s'", node->name, node->raw_children[i]); PUSH(Node **, node->children, node->clen, child); child->parent = node; } int di; DESTROY(node->raw_children, node->rlen, di); }}intcalc_total_weight(Node *node) { int weight = node->weight; for (int i = 0; i < node->rlen; i++) weight += calc_total_weight(node->children[i]); node->total_weight = weight; return weight;}Node *get_root(Node *node) { if (!node->parent) return node; return get_root(node->parent);}char *part1(Node *root) { return root->name;}struct uniq { int weight, count;};#define MOVU(a,b) \ a.weight = b.weight; \ a.count = b.count;voidget_commons(Node **nodes, int len, struct uniq commons[2]) { struct uniq temp; for (int i = 0; i < len; i++) { Node *node = nodes[i]; if (commons[0].weight == 0) { commons[0].weight = node->total_weight; commons[0].count++; } else if (commons[0].weight == node->total_weight) { commons[0].count++; } else if (commons[1].weight == 0) { commons[1].weight = node->total_weight; commons[1].count++; } else if (commons[1].weight == node->total_weight) { commons[1].count++; } else EXPLODE("Third weight %d?!", node->total_weight); } if (commons[1].count > commons[0].count) { // Swap MOVU(temp, commons[1]); MOVU(commons[1], commons[0]); MOVU(commons[0], temp); }}intpart2(Node *root) { calc_total_weight(root); struct uniq commons[2] = {{0, 0}}; int diff = 0; Node *parent = root; for (;;) { commons[0].weight = 0; commons[0].count = 0; commons[1].weight = 0; commons[1].count = 0; get_commons(parent->children, parent->clen, commons); if (commons[1].count == 0) return parent->weight - diff; diff = commons[1].weight - commons[0].weight; for (int i = 0; i < parent->clen; i++) if (parent->children[i]->total_weight == commons[1].weight) parent = parent->children[i]; }}intmain(int argc, char **argv) { Node **nodes = NULL; int part; int len = 0; if (argc != 2 || !((part = *argv[1] - '0') == 1 || part == 2)) { fprintf(stderr, "Usage: %s [part:1|2]\n", argv[0]); return 1; } int c; for (;;) { PUSH(Node **, nodes, len, node_from_line()); if ((c = getchar()) == EOF || c == '\n') break; else ungetc(c, stdin); } resolve_tree(nodes, len); if (part == 1) printf("Name of root: %s\n", part1(get_root(nodes[0]))); else printf("Required weight: %d\n", part2(get_root(nodes[0]))); int j; for (int i = 0; i < len; i++) { Node *node = nodes[i]; free(node->children); free(node->name); } DESTROY(nodes, len, j); return 0;}
m712[email protected] ~ % time ./day7 1 < day7inputName of root: vvsvez./day7 1 < day7input 0.00s user 0.00s system 97% cpu 0.007 [email protected] ~ % time ./day7 2 < day7inputRequired weight: 362./day7 2 < day7input 0.01s user 0.00s system 96% cpu 0.007 total
Valgrind shows no leaks. This time I used a hashmap.

Don't you know what a pastebin is?

Made me smile

I want everyone to be able to modify and study my code and share modified versions of it. This is why I chose GPL3. The copyright notices are there because by default the code license is "All rights reserved" under many jurisdictions which restricts your freedom.

Do you want me to modify and study your comment?

As long as you preserve my copyright notice and the license notice, you are permitted to modify everything.

LOL @ language that doesn't allow doubly linked lists
LOL @ language can't have trees with parents
LOL @ safety from using it for anything but toy projects

Yeah my solution is beyond pajeet level (also I have accidentally deleted it). I'm rewriting it currently.
How is this relevant to this challenge?
Why would you ever do that? Also, how is this relevant to the challenge?

Yeah fuck the borrow checker... Butt ugly. Part 1 works.
extern crate regex;use std::fs::File;use std::io::{BufRead,BufReader};use std::collections::HashMap;use regex::Regex;struct Program { parent: Option, weight: u32,}fn main() { let mut tree = HashMap::new(); let file = File::open("input").unwrap(); let re1 = Regex::new("^(\\w+) \\((\\d+)\\)").unwrap(); let re2 = Regex::new(" (\\w+)").unwrap(); for line in BufReader::new(file).lines() { let line = line.unwrap(); let c = re1.captures(&line).unwrap(); if !tree.contains_key(&c[1]) { tree.insert(String::from(&c[1]), Program { parent: None, weight: c[2].parse::().unwrap(), }); } else { tree.get_mut(&c[1]).unwrap().weight = c[2].parse::().unwrap(); } for d in re2.captures_iter(&line) { if !tree.contains_key(&d[1]) { tree.insert(String::from(&d[1]), Program { parent: Some(String::from(&c[1])), weight: 0, }); } else { tree.get_mut(&d[1]).unwrap().parent = Some(String::from(&c[1])); } } } { let mut ptr = tree.iter().next().unwrap().0; while let Some(ref x) = tree.get(ptr).unwrap().parent { ptr = &x; } println!("Part 1: {}", ptr); } for p in tree.iter_mut() { if let Some(ref parent) = p.1.parent { tree.get_mut(parent).unwrap().weight += p.1.weight; } }}

Isn't that Rust's greatest ally?

It's what is supposed to make Rust safe. It is also the reason why Pajeets will never be able to write Rust.

Day 7 is proving to be a Pajeet Shoah. Now it is 13 hours, 29 minutes since the solution has been posted, which is more than enough to account for Pajeet to get to the solution.

India is 10 and a half hours ahead of EST, so if Pajeet isn't neet and can't work at lunch, he can get started 6 and a half hours after the problem is posted (assuming he finishes work at 5pm and rides his rickshaw very rapidly to his designated coding street).

Should have been 42 minutes, was distracted before hitting send.

Why do you keep posting these? Do you expect people to solve silly challenges on a workday? As you can see the numbers even out after a while when people catch up on the challenges.
Normal people have a life and work and can't spend every waking minute solving stupid challenges on the internet like you neetscum.

well done

But the guys in the front are.
Prove me wrong.

Fuck this bullshit. I hate this language.
extern crate regex;use std::fs::File;use std::io::{BufRead,BufReader};use std::collections::HashMap;use regex::Regex;struct Program { parent: Option, weight: u32,}fn get_children(tree: &'a HashMap, node: &'a str) -> String { let mut x = get_children(tree, node).iter().map(|x| (x.clone(), get_weight(tree, &x))).collect::(); x.sort_by_key(|x| x.1); if x.len() >= 3 { if x.first().unwrap().1 == x.last().unwrap().1 { String::from(node) } else if x.first().unwrap().1 == x[1].1 { find_unbalanced(&tree, &x.last().unwrap().0) } else { find_unbalanced(&tree, &x.first().unwrap().0) } } else { String::from(node) } }fn main() { let mut tree = HashMap::new(); let file = File::open("input").unwrap(); let re1 = Regex::new("^(\\w+) \\((\\d+)\\)").unwrap(); let re2 = Regex::new(" (\\w+)").unwrap(); for line in BufReader::new(file).lines() { let line = line.unwrap(); let c = re1.captures(&line).unwrap(); if !tree.contains_key(&c[1]) { tree.insert(String::from(&c[1]), Program { parent: None, weight: c[2].parse::().unwrap(), }); } else { tree.get_mut(&c[1]).unwrap().weight = c[2].parse::().unwrap(); } for d in re2.captures_iter(&line) { if !tree.contains_key(&d[1]) { tree.insert(String::from(&d[1]), Program { parent: Some(String::from(&c[1])), weight: 0, }); } else { tree.get_mut(&d[1]).unwrap().parent = Some(String::from(&c[1])); } } } let mut ptr = tree.iter().next().unwrap().0; while let Some(ref x) = tree.get(ptr).unwrap().parent { ptr = &x; } println!("Part 1: {}", ptr); let x = get_children(&tree, &get_parent(&tree, &find_unbalanced(&tree, ptr))); let mut y = x.iter().map(|x| (x, get_weight(&tree, &x))).collect::(); y.sort_by_key(|x| x.1); if y.first().unwrap().1 == y[1].1 { println!("Part 2: {}", tree.get(y.last().unwrap().0).unwrap().weight - (y.last().unwrap().1 - y[1].1)); } else { println!("Part 2: {}", tree.get(y.first().unwrap().0).unwrap().weight + (y[1].1 - y.first().unwrap().1)); }}

this is worse than c++

I know you are upset Pajeet, but try and apply a little thinking. There is a clear downward trend, where the decline is accentuated by the presence of relatively harder problems.

These are only stupid challenges to pleb coders who will never master their craft.

Very memory-safe :^)
Just use pointers, man.

you're retarded, people are busy writing code for money instead of wasting time doing shit for free

Yes because it just crashes if .unwrap() fails
No, that would be unsafe.

As if your neet time was worth anything

what does my time have to do with other people working?

t. delusional fanatic
Might as well use a garbage-collected language.

Despite you dubs, we now know you're not a white man. It's just a mentality you will never, ever understand. We go far beyond what is mandated of us, it is why our people have created beautiful civilizations whilst your people live in a squalor which can at best be describe as a failed attempt at a British cargo cult. It is why our people sailed the high seas, went to the moon, and solve AdventOfCode problems; whereas you lack basic infrastructure. Perhaps it wasn't always this way with your people, but being plagued by pettiness and unscrupulousness directed amongst your own kin has rendered your civilization dysfunctional.

Cheating with eval

import refrom collections import defaultdictws = re.compile(r'\s+')def parse_row(l): p = ws.split(l) return p[0], p[1], p[2], p[4], p[5], p[6]vs = defaultdict(lambda: 0)m = 0with open('input.txt', 'r') as f: lines = map(parse_row, f) for t, op, d, c, cmp, cmpv in lines: if eval(f'{c} {cmp} {cmpv}', None, vs): vs[t] += int(d) * (1 if op == 'inc' else -1) m = max(m, vs[t])print(max(vs.values()), m)

Day 8 Golfed
203 characters

import collections as Cv=C.defaultdict(int)m=0for t,p,d,_,c,o,z in map(lambda l:l.split(' '),open('i')): if eval(c+o+z,None,v):v[t]+=int(d)*(1if p=='inc'else-1);m=max(m,v[t])print(max(v.values()),m)

200 characters
ditched 'if' statement because I can implicitly convert bool to int
import collections as Cv=C.defaultdict(int)m=0for t,p,d,_,c,o,z in map(lambda l:l.split(' '),open('i')): v[t]+=eval(c+o+z,None,v)*int(d)*(1if p=='inc'else-1);m=max(m,v[t])print(max(v.values()),m)

day 8. Nothing fancy. void heard_you_like_registers(string input){ unordered_map reg; auto compare = [](int a, string_view op, int b){ return op == "==" ? a == b : op == "!=" ? a != b : op == "" ? a > b : a >= b; }; int highest = int((~0u >> 1) + 1); for (string_view line : input | split(by_line)){ auto [modif, ins, q, x, compreg, comp, compval, rest] = parse_only(line, by_alpha, by_alpha, by_int, by_alpha, by_alpha, by_word, by_int); if (compare(reg[compreg], comp, stoi(string(compval)))) if (int cur = reg[modif] += stoi(string(q)) * (ins == "inc" ? 1 : -1); cur > highest) highest = cur; } cout

197 characters
no need to compare strings by equality here :D
import collections as Cv=C.defaultdict(int)m=0for t,p,d,_,c,o,z in map(lambda l:l.split(' '),open('i')): v[t]+=eval(c+o+z,None,v)*int(d)*(1if p>'i'else-1);m=max(m,v[t])print(max(v.values()),m)

#!/usr/bin/env python3# Copyright m712 2017.## This program is free software: you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation, either version 3 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program. If not, see>.import sysdef parse(input): regs = {} instrs = [] for line in filter(lambda x: x, input.split('\n')): reg, instr, by, _, oreg, comp, onum = line.split(' ') regs[reg] = 0 instrs.append([reg, instr, by, oreg, comp, onum]) return (regs, instrs)def run(regs, instrs): mv = 0 comps = { "": lambda a,b: a>b, "==": lambda a,b: a==b, "=": lambda a,b: a>=b, "!=": lambda a,b: a!=b, } for i in instrs: reg, instr, by, oreg, comp, onum = i if comp not in comps: raise ValueError("Unknown comparison {}".format(comp)) if not comps[comp](regs[oreg], int(onum)): continue if instr == "inc": regs[reg] += int(by) elif instr == "dec": regs[reg] -= int(by) else: raise ValueError("Unknown instruction {}".format(instr)) mv = max(mv, regs[reg]) return (regs, mv)if __name__ == "__main__": print("Enter input:") regs, mv = run(*parse( print("Maximum register:", max(regs.values())) print("Maximum value a register has had:", mv)
Did a shitty version of this in a repl in ~15 minutes and got 364th and 447th worldwide respectively. C version should come fairly soon.


Cheating is for niggers.


Mathematica. This is a simple one for any language with first class functions.

Slightly modified to make comparison more efficient and use a more appropriate parsing function: void heard_you_like_registers(string input){ unordered_map reg; auto compare = [](int a, string_view op, int b){ return op[0] == '=' ? a == b : op[0] == '!' ? a != b : op[0] == '

Still longer than Python with 197 characters.

I guess I can also replace the ins == "inc" with ins[0] == 'i', while I'm at it.

It would be longer by 1 character if you don't count removable whitespace.

And I didn't get quads either, but such is life.

I was more going for efficiency than code length for that one, though.

It is irrelevant here. Even python solution finishes in a blink of an eye or faster.
That's autism.

Wtf I love Rust now
extern crate regex;use std::fs::File;use std::io::{BufRead,BufReader};use std::collections::HashMap;use regex::Regex;fn main() { let mut registers: HashMap = HashMap::new(); let file = File::open("input").unwrap(); let re = Regex::new("^(\\w+) (\\w+) (-?\\d+) if (\\w+) ([!=]{1,2}) (-?\\d+)$").unwrap(); let mut max = 0; for line in BufReader::new(file).lines() { let line = line.unwrap(); let c = re.captures(&line).unwrap(); if match &c[5] { "==" => *registers.get(&c[4]).unwrap_or(&0) == c[6].parse::().unwrap(), "!=" => *registers.get(&c[4]).unwrap_or(&0) != c[6].parse::().unwrap(), "=" => *registers.get(&c[4]).unwrap_or(&0) >= c[6].parse::().unwrap(), "" => *registers.get(&c[4]).unwrap_or(&0) > c[6].parse::().unwrap(), _ => panic!(), } { let r = registers.entry(String::from(&c[1])).or_insert(0); match &c[2] { "inc" => *r += c[3].parse::().unwrap(), "dec" => *r -= c[3].parse::().unwrap(), _ => panic!(), } max = std::cmp::max(*r, max); } } let part1 = *registers.values().max().unwrap(); println!("Part 1: {}", part1); println!("Part 2: {}", std::cmp::max(part1, max));}

You know what's also autistic?

Code golf is a legitimate thing btw.

Show us the day 7 solution in Rust which is not ugly as fuck.

And so is optimization tbh fam.

Here u go fam
use std::fs::File;use std::io::{BufRead,BufReader};use std::collections::HashMap;fn main() { let mut registers = HashMap::new(); let mut max = 0; let file = File::open("input").unwrap(); for line in BufReader::new(file).lines() { let line = line.unwrap(); let c: Vec = line.split(' ').collect(); let a = *registers.get(c[4]).unwrap_or(&0); let b = c[6].parse::().unwrap(); let d = c[2].parse::().unwrap(); if match c[5] { "==" => a == b, "!=" => a != b, "=" => a >= b, "" => a > b, _ => panic!(), } { let r = registers.entry(String::from(c[0])).or_insert(0); match c[1] { "inc" => *r += d, "dec" => *r -= d, _ => panic!(), } max = std::cmp::max(*r, max); } } println!("Part 1: {}", registers.values().max().unwrap()); println!("Part 2: {}", max);}

Haven't golfed variable names, but getting smaller...

I said day 7

Oh right. No. Maybe Steve will.

A bit smaller removing that switch. Forgive me, but also posted this version on reddit.

Why don't you just input.splitlines()?

Meh. I could use splitlines. I didn't know about it. The filter is there to strip empty lines.
Also, I'm dumb and didn't read the pydoc3 for filter. Passing None should do it.
>>> input = open("day7input").read().splitlines()>>> input["ughg (88)", "zhnk (35) -> ughg, nzms, aaj", ..., ""]>>> # See the empty string at the end which fucks up the parser>>> filter(None, input)["ughg (88)", "zhnk (35) -> ughg, nzms, aaj", ..., "deutsch (1488) -> hitler"]

Day 7:
Time: 0.86 ms
>inb4 Rc
The only reason I did that is because I wanted to try out the std::cell module. It is not necessary to do that. A lot of time is probably spent checking accesses inside of RefCell. Going to see how much faster it is with UnsafeCell later today.

Day 8:
Time: 0.38 ms
Pretty verbose. I'm probably going to make it shorter later today.

[email protected] ~ % grep unwrap | wc -l13

LOL. >>834113
stfu you stupid turkoachh

Shit. I only looked at 'wc -l' and didn't realize you were grepping for unwrap.
How is this worse than using Exceptions for control flow? Kill yourself retarded python nigger.

grep unwrap >>834487 | wc -l6
So? Would you rather prefer undefined behavior?

Please, it's turkroach.

match &c[5] { "==" => *registers.get(&c[4]).unwrap_or(&0) == c[6].parse::().unwrap(), "!=" => *registers.get(&c[4]).unwrap_or(&0) != c[6].parse::().unwrap(), "=" => *registers.get(&c[4]).unwrap_or(&0) >= c[6].parse::().unwrap(), "" => *registers.get(&c[4]).unwrap_or(&0) > c[6].parse::().unwrap(), _ => panic!(), }
comps = { "": lambda a,b: a>b, "==": lambda a,b: a==b, "=": lambda a,b: a>=b, "!=": lambda a,b: a!=b, }... if comp not in comps: raise ValueError("Unknown comparison {}".format(comp)) if not comps[comp](regs[oreg], int(onum)): continue
You tell me.

I'd prefer a language that doesn't add to the work. Rust "removes" the baggage of memory safety woes but then adds back twice the baggage with ass-backwards "safety" calls and the hellspawn known as borrowck.

Not to mention your code will explode with a generic error making it harder to debug while the python code will tell you what the unknown comparison was.
polite sage

the moment you posted in this thread it turned to shit. fuck off turkroach

Also, memory safety has been a solved thing for many years now. Use reference counting. If you have something that's allocated in your struct by another place remember to unref when freeing. It's this simple. Those who can't do something this simple should just stick to interpreted languages or garbage collectors.
polite sage again


as i said: pajeet
polite sage. im going to stop engaging you now.

Shut the fuck up. You were the one who started this flamewar about languages. Nobody even shat on others' code until you came in at and started shitposting.

pic related
Give one argument against it.

How the fuck are these 2 things connected? Also there's no such thing as compiled or interpreted language.
You don't know what you're talking about dood.

why use splitlines at all if you can simply iterate the file like in

> Rc

Please see my updated solution in . None of the unwraps is used to solve a problem that could be solved using reference counting.

Rust doesn't have exceptions. open returns an `Option` which can either contain a `File` or it can be `None`. unwrap gets the File (if open was successful) or crashes the program.
No exceptions in Rust. lines() expects the BufReader to be valid UTF-8, because if it's not, splitting it up into lines is not well-defined. lines() also returns `String`s, which must be UTF-8 in Rust. If you want a different encoding, use byte arrays. Same as in Python 3. If invalid UTF-8 is encountered, the iterator returns a None.
No exceptions. get returns an `Option` which either contains a reference to an i32 or is None if no such element is found. If it is None, we can continue to work with the default value 0.
>let b = c[6].parse::().unwrap();
>let d = c[2].parse::().unwrap();
Again, no exceptions. parse gives an `Option` which contains the result, an i32, or None.
max only makes sense if the iterator it is called on yields at least one element. If it doesn't, there's an error. To return an error, an `Option` is used.



macro_rules! cmp { (($op:expr, $l:expr, $r:expr), ($($cmp:tt),*)) => { match $op { $(stringify!($cmp) => { $l $cmp $r })* _ => { unreachable!() } } }}fn main() { let instant = std::time::Instant::now(); let mut registers = std::collections::HashMap::new(); let mut b = 0; for l in INPUT.lines() { let mut iter = l.split_whitespace(); macro_rules! parse { ($iter:ident) => {( $, $, $ )} } let (l1, op1, r1) = parse!(iter);; let (l2, op2, r2) = parse!(iter); let l2 = *registers.entry(l2).or_insert(0); if cmp!((op2, l2, r2), (=, ==, !=)) { let l1 = registers.entry(l1).or_insert(0); match op1 { "inc" => { *l1 += r1; } "dec" => { *l1 -= r1; } _ => { unreachable!() } } b = std::cmp::max(b, *l1); } } let a = registers.values().max().unwrap(); let d = instant.elapsed(); println!( "Part 1: {}\nPart 2: {}\nTime: {} ms", a, b, (d.as_secs() as f64 + d.subsec_nanos() as f64 / 1000000000.0) * 1000.0 );}
Now that is some breathtakingly beautiful Rust code. macros_rule! tbh

day 8 was fun. ocaml:type modop = Inc | Dectype condop = Gt | Ge | Eq | Ne | Lt | Letype cond = If of (string * condop * int)let input8 = [ "ba", Dec, 37, If ("znx", Ne, 0); "zrn", Inc, -344, If ("znx", Gt, -9);...]let day8 input = let highest = ref 0 in let registers = Hashtbl.create 100 in let get reg = match Hashtbl.find_opt registers reg with None -> 0 | Some r -> r in let put reg n = if n > !highest then highest := n; Hashtbl.replace registers reg n in let inc reg n = put reg (get reg + n) in let dec reg n = put reg (get reg - n) in let alter op reg n = match op with Inc -> inc reg n | Dec -> dec reg n in let check reg cond n = (match cond with | Gt -> (get reg) > n | Ge -> (get reg) >= n | Eq -> (get reg) = n | Ne -> (get reg) n | Le -> (get reg) (get reg) < n) in let rec loop list = match list with | [] -> let (reg, v) = Hashtbl.fold (fun k v (acc_k, acc_v) -> if v > acc_v then (k, v) else (acc_k, acc_v)) registers ("fake", min_int) in (reg, v, !highest) | (reg1, op, n, If (reg2, cond, v)) :: rest -> if check reg2 cond v then alter op reg1 n; loop rest in loop input

pic related indeed
read it from top to bottom.


not an argument

No need to be so rusty friendo
kill yourself turkroach


how is unwrap better than #define CHECK(expr) \ if ((expr)) { \ perror(__func__); \ abort(); \ } //#define CHECK_NULL(x) CHECK(!(x))#define CHECK_NZERO(x) CHECK((x))#define CHECK_LTZERO(x) CHECK((x) < 0)// ...FILE *f;CHECK_NULL(f = fopen("dicks.jpg", "r"));// sock;CHECK_NZERO(getaddrinfo(...));// ...CHECK_LTZERO(sock = socket(domain, type, protocol));CHECK_LTZERO(connect(sock, "", 7));?
Actually, I can kinda see the point of .unwrap() (fixes the butt-ugly inconsistency of stdlib return values, one function for checking), but why not just unwrap in the first place? Why can't you say let f = File::open?("dicks") or something? (notice the ?)
Would Rustfagsdevs consider adding ? functions for returning an Option and exploding by default?

Added in v1.22
>The headline feature for this release is one many have been anticipating for a long time: you can now use ? with Option! About a year ago, in Rust 1.13, we introduced the ? operator for working with Result. Ever since then, there’s been discussion about how far ? should go: should it stay only for results? Should it be user-extensible? Should it be usable with Option?
But that only works if the function returns an Option. The main function doesn't return anything so you can't do it there. There is something in the works to address this though.

This is your brain on delusion.

also File::open returns a Result not an Option

What I was trying to say is, if you want to check errors yourself, you should be able to do let f = File::open?("dicks").unwrap() (which is the current behavior) but if you want the stdlib to crash the program you should be able to just do let f = File::open("dicks").

that is absolutely awful though. why would you want to crash your program?

Isn't the entire point of .unwrap() crashing your program if the value is None? The second statement should have an implicit unwrap was what I was saying.

But you only use unwrap when you don't want to do propert error handling or when you are sure that it is Some/Ok.
You propose to implicitly (Rust is all about being explicit btw) panic. But in most real world cases you don't want that.


fuck off kampfy

go away from programming until it's too late.
people like you created fucking PHP and Javascript.

so after it is too late i can come back?
LOL. learn 2 english, kiddo.


wow you sure convinced me

Well, you wouldn't use it where you don't have Some. If you can keep which calls need a .unwrap() in your head, you can most likely keep which calls need a ?.
explicity != verbosity. Rust is verbose. If I wanted the option to do error checking myself I could just use File::open?(name) and get an Option. This is being explicit. Requiring .unwrap() on every call that returns Some/Ok is being verbose.

Error handling in Rust is explicit. You can't ignore the possibility of an error like you could in languages that have unchecked exceptions or C. This may be verbose, but it most definitely is explicit.
You don't have to use unwrap, in fact it is discouraged to do that in real world code.
Also you are literally arguing in favor of having implicit error handling by default.

they why does every rust code in this thread have copious amounts of unwrap in it?

because it isnt real world code? because as long as the input isnt bad it wont panic? because even if it panics nobody cares?

day 9. still easy enough. void stream_processing(string_view input){ size_t level = 0, score = 0, garbage_count = 0;not_garbage: for (; !input.empty(); input.remove_prefix(1)) if (input[0] == '{') score += ++level; else if (input[0] == '}') --level; else if (input[0] == '') goto not_garbage; else ++garbage_count;epilogue: cout

I should probably add an "input.remove_prefix(1);" before the "goto not_garbage;" to save an iteration of the first loop. Meh, not a big deal.

183 characters
too lazy to golf it further, I think it must be possible but fuck it.

import ret=re.sub('!.','',open('i','r').read())g=re.compile('')s=0l=0for c in g.sub('',t): if c=='{':l+=1 elif c=='}':s+=l;l-=1print(s,sum(len(x)-2for x in g.findall(t)))

another fun day, though a bit easy. ocaml:open Printf let clean s = let len = String.length s in let scores = ref 0 in let gc = ref 0 in let rec garbage i cb = match s.[i] with | '!' -> garbage (i + 2) cb | '>' -> cb (i + 1) | c -> (gc := !gc + 1; garbage (i + 1) cb) and group i parens score = match s.[i] with | '!' -> group (i + 2) parens score | '

damn, I missed that ! only shows up in garbage

Wouldn't have looked much better. Also, I don't know if GCC would have been able to optimize it into something as efficient.

More hard challenges will be released on the
The other days are normal/easy challenges.


Good job.

Why has this thread been silently anchored? Does code trigger Holla Forums?

The bumplimit is 400 posts. Make a new thread.

Ahh. We might as well keep this thread until full.

Wtf this shit is too easy:
fn main() { let mut iter = INPUT.iter(); let mut garbage = false; let mut group = 0; let mut solution_part1 = 0; let mut solution_part2 = 0; while let Some(&b) = { match b { b'>' => { garbage = false; } b'!' => {; } b'

Nice work.


ocaml in (almost) the style of your rust:let clean2 s = let len = String.length s in let i = ref 0 in let b = ref ' ' in let iter_next () = if !i = len then false else (b := s.[!i]; incr i; true) in let garbage = ref false in let group = ref 0 in let answer1 = ref 0 in let answer2 = ref 0 in while iter_next () do match !garbage, !b with | _, '>' -> garbage := false | _, '!' -> ignore (iter_next ()) | false, '

How many of you guys actually log into the site?

you have to log into it to get the puzzles. IIRC I just used a github throwaway.

New thread:
New thread:
New thread:
New thread: