[–]▶ No.830716>>830860 >>830958 [Watch Thread][Show All Posts]
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.
http://adventofcode.com/
▶ No.830717>>830761 >>831825
Day 1 in Rust: https://play.rust-lang.org/?gist=b369f967792ec62e7eb875201ff0a278&version=stable
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::<u32>()
);
}
▶ No.830756>>831859
Day 1 in C: http://codepad.org/CiFpQwfb
#include <stdio.h>
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;
}
▶ No.830760>>831859
1 in Python http://codepad.org/gyUmadgj
[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]
▶ No.830761>>830763
>>830717
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<I: Clone + Iterator<Item=u32>>(iter: I, step: usize) -> u32 {
iter.clone()
.zip(iter.cycle().skip(step))
.filter(|&(a, b)| a == b)
.map(|(a, _)| a)
.sum()
}
▶ No.830763>>830767
>>830761
What is part 2? Do I need to log in to see it?
▶ No.830769
http://codepad.org/LPJ86RtI
#include <stdio.h>
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;
}
http://codepad.org/cBpouX3o
#!/usr/bin/python3
for 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)))
▶ No.830771
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")))
▶ No.830841
$_=<>;chomp;@a=split//;for(0..$#a){$b+=$a[$_]if$a[($_+1)%$#a]==$a[$_]};print"$b".$/
$_=<>;chomp;@a=split//;for(0..$#a){$b+=$a[$_]if$a[($_+$#a/2)%$#a]==$a[$_]};print"$b".$/
▶ No.830859
echo 1122 | awk '{split($0,c,"");r=0;for(i=1;i<=length($0);i++){r+=(c[i]==c[i%length($0)+1])?c[i]:0};print r}'
echo 123123 | awk '{split($0,c,"");r=0;for(i=1;i<=length($0);i++){r+=(c[i]==c[(i+length($0)/2-1)%length($0)+1])?c[i]:0};print r}'
▶ No.830860>>830862 >>830864
>>830716 (OP)
do i get paid or win a job for solving these problems?
▶ No.830862
>>830860
Look, you're trapped here forever. Solving these is an option to kill your boredom in this shithole and to show off languages.
▶ No.830864>>830879
>>830860
>Solving these is an option to kill your boredom in this shithole
thats what shitpostings for cunt
▶ No.830866>>830879
>>830846
>MUUUUUH (((BOTNET)))
have you considered killing yourself?
▶ No.830879>>830908
>>830864
>>830866
Shut up and code.
▶ No.830883
>>830846
My thoughts exactly...
▶ No.830888>>831749 >>831859
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);
▶ No.830889
>>830846
b-but anon there's no other coding challenge sites
▶ No.830908>>830915 >>830926 >>830944 >>830952 >>831068 >>831075
>>830879
ITT faggots try to broadcast their /tech/ 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.
▶ No.830915>>830922
>>830908
$e="u";$a="r";$l="g";$x="o";$c="y";$o="e";$d="a";$s="'";print$c.$x.$e.$s.$a.$o.$".$l.$d.$c.$".$/
▶ No.830922
>>830915
spd-say -t child_female -p +100 faggot
▶ No.830926
>>830908
Lighten up mate, these are only for fun.
▶ No.830944
>>830908
>maintainable code
>for a Christmas challenge
who cares, faggot
▶ No.830952
>>830908
Calm down and take your pills. Also
>posting their favourite esoteric languages that AREN'T used in INDUSTRY
C, Python, Perl, Awk aren't used in the industry?
▶ No.830958>>830961
>>830716 (OP)
>The night before Christmas, one of Santa's Elves calls you in a panic. "The printer's broken! We can't print the Naughty or Nice List!" By the time you make it to sub-basement 17, there are only a few minutes until midnight. "We have a big problem," she says;
>she
into the trash
▶ No.830961
>>830958
Here's something to soothe your gay rage
▶ No.830982>>830997
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";
▶ No.830997
>>830982
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";
▶ No.831049
C double plus
void inverse_captcha1(std::string input)
{
input.push_back(input[0]);
std::cout << std::inner_product(input.begin(), input.end() - 1, input.begin() + 1,
0, [](int acc, char c){ return acc + c; }, [](char a, char b){ return a == b ? a - '0' : 0; });
}
void inverse_captcha2(std::string input)
{
size_t orig_sz = input.size(), orig_sz2 = orig_sz / 2;
input.resize(3 * orig_sz2);
std::copy_n(begin(input), orig_sz2, begin(input) + orig_sz);
std::cout << std::inner_product(input.begin(), input.begin() + orig_sz, input.begin() + orig_sz2,
0, [](int acc, char c){ return acc + c; }, [](char a, char b){ return a == b ? a - '0' : 0; });
}
▶ No.831075
>>830908
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!"
▶ No.831079>>831085
>>831068
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.
▶ No.831085>>831118
>>831079
>this is what /g/tards actually believe
▶ No.831091>>831094
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
▶ No.831094>>831096 >>831104
>>831091
>ocaml or some shit
>no pattern matching
pajeet
▶ No.831095>>831097
>>830846
get a throwaway github. it's the best of the bunch.
they fired the safe-space tranny for persistently making real girls uncomfortable
▶ No.831096>>831106
▶ No.831097>>831099 >>831102
>>831095
>github
>$7 silver shekels a month
>"""""""the best""""""""
>not bitbucket
>unlimited free private suppositories
▶ No.831099>>831101
>>831097
Github is free, you don't have to pay a monthly fee.
▶ No.831101>>831103
>>831099
You have to pay a monthly fee for private repos.
▶ No.831102
>>831097
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, anon.
▶ No.831103>>831105
>>831101
Yeah but otherwise it's free.
▶ No.831104>>831114
>>831094
I hope this is more to your taste, anon.
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
▶ No.831105>>831130
>>831103
>you have to pay for a private profile
>"it's free"
▶ No.831106
>>831096
>not an argument
i believe the word you're looking for is "parameter", pajeet
▶ No.831114
>>831104
it annoys me that this piece of shit rewrite is actually better for not producing bullshit answers:
utop # adv_faggotry "hi there";;
- : int = 112
utop # use_of_toilet "hi there";;
Exception: (Failure "non-digit found in string").
Raised at file "pervasives.ml", line 32, characters 22-33
Called from file "puzzle.ml", line 44, characters 25-36
Called from file "toplevel/toploop.ml", line 180, characters 17-56
▶ No.831118
>>831085
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.
▶ No.831130>>831133
>>831105
do you bitch when the cable company doesn't give you free pay-per-view?
▶ No.831133>>831139
▶ No.831139>>831157
>>831133
<not watching television
▶ No.831157
>>831139
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...
▶ No.831170
>awarding (((yellow stars))) to people
oy vey!
▶ No.831174>>831178
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.
▶ No.831178>>831181
>>831174
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)
▶ No.831180
there are A LOT of chinks on the leaderboard
▶ No.831181>>831182 >>831186
>>831178
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.
▶ No.831182
>>831181
Very gay indeed. Why can't people just do it for free fun?
▶ No.831183>>831184
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.
▶ No.831184>>831185
>>831183
>bully me
POST IT!
▶ No.831185
>>831184
I ugh, don't have an account.
▶ No.831186>>831187
>>831181
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
▶ No.831187>>831188
>>831186
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.
▶ No.831188>>831190
>>831187
totally defeats the point of rushing then imo
▶ No.831190>>831193 >>831195
>>831188
Yeah. Funny enough the number #10 guy used Mathematica.
https://www.reddit.com/r/adventofcode/comments/7h0rnm/2017_day_2_solutions/dqn9gd9/
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.
▶ No.831193
>>831190
>However, despite the Apple badge, I am not gay.
>apple
>not gay
▶ No.831195
>>831190
I take that back, my part1 is marginally faster.
I haven't seen anyone using Ada yet.
▶ No.831196
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.
https://www.reddit.com/r/adventofcode/comments/7h0rnm/2017_day_2_solutions/dqn9mju/
▶ No.831197>>831198
Multithreaded solution: https://play.rust-lang.org/?gist=a66c52c2c097b90b9aa02b2e5b2e8b20&version=stable
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::<i32>();
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::<i32>());
}
▶ No.831198>>831222
>>831197
I don't think the input size necessitates threading anon
▶ No.831202
I'm waiting for the Enterprise Java and relational database solution.
▶ No.831203>>831205
Could someone please screenshot part 2?
▶ No.831219
day 2
let 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 m
just a string list list for a 'matrix'
▶ No.831220>>831221 >>831223
>OP shill is copy paste of a paragraph from site and a link
>junk lingo: variety of skill levels, self-contained, appropriate, stay sharp, learning to code, build on a theme
>hey guys blah blah backstory Santa needs you to count the number of vowels in these words
>zero effort leaderboard for who submitted first
perhaps the most plebbit thing on this board
▶ No.831221
>>831220
>no code
spotted the butthurt LARPer
▶ No.831222
>>831198
It doesn't necessitate dealing with empty cells and rows either...
>>831205
Thanks!
https://play.rust-lang.org/?gist=62a11d20dbdcdb8e26e66efd08f0a340&version=stable
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::<i32>();
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::<i32>());
}
▶ No.831223
>>831220
say what you want about the leaderboard but the digimon christmas story isn't bad
▶ No.831227>>831230 >>831240
▶ No.831230>>831231 >>831234
>>831227
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
▶ No.831231
>>831230
that's run as: sudo perf stat -e cycles -e instructions ./p
I don't use perf much, just copying someone who uses it
▶ No.831234>>831235
>>831230
I just included the time to show that it runs <1ms (which is a requirement of aoc. read the lore). my solution isn't meant to be the fastest also the timing was taken on play.rust-lang.org not on my pc.
▶ No.831235>>831236
>>831234
There is no hard requirement on performance you LARPfag.
▶ No.831236>>831238
>>831235
>When your eyes can focus again, everything seems a lot more pixelated than before. She must have sent you inside the computer! You check the system clock: 25 milliseconds until midnight. With that much time, you should be able to collect all fifty stars by December 25th.
>Collect stars by solving puzzles. Two puzzles will be made available on each day millisecond in the advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!
▶ No.831238>>831240 >>831241
>>831236
Are you just pretending to be retarded?
▶ No.831240>>831242 >>831244 >>831272
>>831227
i removed loops: https://play.rust-lang.org/?gist=4628d63c3e21ea1cc42f847ced908dfc
Time: 0.028 ms
>>831238
>le smug aniuuuuh
shit. you won. i am sooooooo mad now.
▶ No.831241
>>831238
he just doesn't want to compare rust against ocaml for no reason
meanwhile:
$ time python -c 'print 1'
1
real 0m0.039s
user 0m0.023s
sys 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.
▶ No.831242>>831243
>>831240
>there is no hard requirement on performance
>posts some part of the shitty lore that accompanies the challenges
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.
▶ No.831243
>>831242
>muh hard requirement
Please quote me where i said that.
>rustfag
Found the triggered anti Rust shill. Post code or kill yourself.
▶ No.831244>>831246
>>831240
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.
▶ No.831246>>831248 >>831249
>>831244
>Do I get those numbers when I log in?
Yes
>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.
▶ No.831248>>831250
>>831246
>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.
▶ No.831249
>>831246
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.831250>>831251
>>831248
No it is part of the challenge. Read the lore. You were sent into the computer.
>The night before Christmas, one of Santa's Elves calls you in a panic. "The printer's broken! We can't print the Naughty or Nice List!" By the time you make it to sub-basement 17, there are only a few minutes until midnight. "We have a big problem," she says; "there must be almost fifty bugs in this system, but nothing else can print The List. Stand in this square, quick! There's no time to explain; if you can convince them to pay you in stars, you'll be able to--" She pulls a lever and the world goes blurry.
▶ No.831251>>831252
>>831250
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.831252
>>831251
>content-type : text/plain
No I receive my input over HTTP.
▶ No.831254
>>831253
Don't worry. I am merely pretending to be retarded.
▶ No.831271>>831279 >>831280
$*IN.lines.map({[-] .comb(/\d+/).map(+*).minmax.bounds.reverse}).sum.say
$*IN.lines.map({[/] .comb(/\d+/).combinations(2).map({.sort(-*)}).first({$_[0]%%$_[1]})}).sum.say
▶ No.831272
▶ No.831279>>831280
>>831271
Horrifying indeed. What language is this?
▶ No.831280>>831287
>>831271
>>831279
On second thought, is this perl6? It better not be.
▶ No.831287>>831289
▶ No.831289>>831306 >>831311
>>831287
Does it still have worse performance than perl5?
▶ No.831306>>831312
>>831289
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.
▶ No.831311>>831545
Yesterdays problem:
my$a=get.comb.list;zip($a.list,$a.rotate(1)).map({$_[0]==$_[1]&&$_[0]}).sum.say
my$a=get.comb.list;zip($a.list,$a.rotate($a.elems/2)).map({$_[0]==$_[1]&&$_[0]}).sum.say
>>831289
It's slow as shit
▶ No.831312>>831316
>>831306
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.
From https://perl6.org/:
>Hi, my name is Camelia. I'm the spokesbug for Perl 6, the plucky little sister of Perl 5. Like her world-famous big sister, Perl 6 intends to carry forward the high ideals of the Perl community. Perl 6 is currently being developed by a team of dedicated and enthusiastic volunteers. You can help too. The only requirement is that you know how to be nice to all kinds of people (and butterflies). Go to #perl6 (irc.freenode.net) and someone will be glad to help you get started.
▶ No.831316
>>831312
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.
▶ No.831319>>831322 >>831326
▶ No.831322>>831323
>>831319
While these posts are incredibly shitty there are some true aspects to them.
>people shit on you when you try to learn
>stick with it and git gud
>eventually you also shit on noobs
the cycle never ends
▶ No.831323
>>831322
Forgot to say that these blogposts are linked on perl6.org in one of those useless categories on the top.
▶ No.831325>>831372
i kinda like how terse perl6 can be but all this faggotry surrounding the language is unbearable
▶ No.831326
>>831319
>Ignoring trolls and people whose knowledge of Perl ends with the line-noise quips, Perl is the Grandfather of Web, the Queen of Backwards Compatibility, and Gluest language of all the Glues. Perl is installed by default on many systems, and if you're worthy enough to wield its arcane magic, it's quite damn performant.
>Rakudo language, on the other hand, is none of those things.
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!
▶ No.831372>>831552
▶ No.831481
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)))))
▶ No.831524>>831525
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())
▶ No.831525>>831557
>>831524
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
▶ No.831545
>>831311
Now do it in a real language (like C)
▶ No.831552
>>831372
J advantage:
>KEI worked on it
>Jsoftware likes you
J disadvantage:
>more APL-like in a bad way
>Roger's gone, working for APL company now. deadlang?
K advantage:
>good syntax
>lot of good design
>open-source implementations [because Kx hates you and hid away their version after it caught popularity]
K disadvantage:
>Kx hates you fucking LARPers. Go jump off a bridge, nerd
>no KEI, no J labs, no books, impoverished red-headed stepchild lang
▶ No.831557
>>831525
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.
▶ No.831584>>831702 >>832051 >>833996 >>834007
Today's thing + some miscellaneous machinery to ease future parsing
using namespace std;
template<typename P> 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(in.data() + start, cur - start);
return true;
}
template<typename P> 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<typename P> struct split_t
{
constexpr auto begin() const { return split_iter<P>{sv, string_view(), 0, p}; }
constexpr auto end() const { return nullptr; }
string_view sv; P p;
};
template<typename P> constexpr auto split(string_view sv, P&& p) { return split_t<P>{sv, forward<P>(p)}; }
template<typename P> constexpr auto split(P&& p) { return [p = forward<P>(p)](string_view sv){ return split(sv, p); }; }
template<typename Rit, typename F> struct map_to_iter
{
template<typename T> 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<typename R, typename F> struct map_to_t
{
constexpr auto begin() const { return map_to_iter<decltype(r.begin()), F>{r.begin(), f}; }
constexpr auto end() const { return r.end(); }
R r; F f;
};
template<typename R, typename F> constexpr auto map_to(R&& r, F&& f) { return map_to_t<R, F>{forward<R>(r), forward<F>(f)}; }
template<typename F> constexpr auto map_to(F&& f) { return [f = forward<F>(f)](auto&& r){ return map_to(forward<decltype(r)>(r), f); }; }
template<typename A, typename B> constexpr auto operator|(A&& a, B&& b) { return forward<B>(b)(forward<A>(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 << sum;
}
void corruption_checksum2(string input)
{
auto sum = 0u; vector<unsigned int> prev;
for (string_view line : input | split([](char c){ return c != '\n'; })){
for (unsigned int v : line | split([](char c){ return !isspace(c); }) | map_to([](auto w){ return stoul(string(w)); })){
bool inv = false;
if (auto it = find_if(prev.begin(), prev.end(), [&](auto p){ return !(p % v) || (inv = !(v % p)); }); it != prev.end()){
sum += inv ? v / *it : *it / v;
break;
}
prev.push_back(v);
}
prev.clear();
}
cout << sum;
}
▶ No.831702>>831751
>>831584
Parallelized version of day 2
vector<string_view> regroup_lines(string_view input)
{
const size_t n_thr = omp_get_max_threads();
vector<string_view> 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<string_view> 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 << sum;
}
void corruption_checksum2_parallel(string input)
{
vector<string_view> subinput = regroup_lines(input);
auto sum = 0u;
#pragma omp parallel for reduction(+:sum)
for (int i = 0; i < omp_get_max_threads(); ++i){
vector<unsigned int> prev;
for (string_view line : subinput[i] | split([](char c){ return c != '\n'; })){
for (unsigned int v : line | split([](char c){ return !isspace(c); }) | map_to([](auto w){ return stoul(string(w)); })){
bool inv = false;
if (auto it = find_if(prev.begin(), prev.end(), [&](auto p){ return !(p % v) || (inv = !(v % p)); }); it != prev.end()){
sum += inv ? v / *it : *it / v;
break;
}
prev.push_back(v);
}
prev.clear();
}
}
cout << sum;
}
▶ No.831746>>831747
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 ()) m
let 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 1
let 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) 0
let 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 0
let spy_found = ref false
let looking_for n =
spy_found := false;
spy_target := n
let 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 sum
let 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)
▶ No.831747
>>831746
oh and safe_get:
let safe_get m x y =
try
Array.get (Array.get m y) x
with
Invalid_argument _ -> 0
▶ No.831749>>831753
>>830888
>semicolons
????????
▶ No.831751>>832200
>>831702
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 << 0, void();
for (size_t i = 0, j = 0;; i += 8, j += i)
if (j >= 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 << lvl + (lvl_side_dist < 0 ? -lvl_side_dist : lvl_side_dist), void();
}
}
void spiral_memory2(size_t val)
{
size_t upper_bound_sz = [&]{
for (size_t i = 0, j = 0;; i += 8, j += i)
if (j >= val) return 3 + (i >> 2);
}(), upper_bound_sz2 = upper_bound_sz >> 1;
vector<size_t> 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 <= y + 1; ++j)
for (int i = x - 1; i <= x + 1; ++i)
sum += grid[at(i, j)];
return sum;
}()); newval > val)
return cout << newval, void();
} while (++counter < side);
}
}
}
▶ No.831753
>>831749
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?
▶ No.831763>>831767
>day 3 solutions look like utter shit
>no neat tricks to make code tidy, it's always going to look like shit because there's no elegant way to do this
cool
▶ No.831767>>831769
>>831763
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.
▶ No.831769
>>831767
e.g. rustfag:
>It was also kind of unfortunate that my solution for the first part was completely useless for the second part.
▶ No.831798>>831801 >>832043
I'm not proud. https://play.rust-lang.org/?gist=e075c3521573c8c2c36d8316f0b096e6&version=stable
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();
}
▶ No.831801
>>831798
Damn. I just want to say that this isn't me.
▶ No.831823>>831824 >>831825 >>831945
Question about the day1 challenge partA
What should this testcase return?
>9919999
▶ No.831824>>831945
▶ No.831825>>831827
>>831823
just change the input here: >>830717
▶ No.831827>>831828 >>831834 >>831858
>>831825
I tested a C and a Python version from further up and they both returned 36
▶ No.831828>>831829 >>831834
>>831827
well they are wrong
▶ No.831829>>831857
>>831828
The rust one returns 45 so it works fine but those other anons fucked it up.
>using C
>using Python
confirmed for shit i guess
▶ No.831834>>831859
▶ No.831835
is there an 8chan private leaderboard yet?
▶ No.831857
>>831829
ocaml's fine though:
utop # sum_faggotry "9919999";;
- : int = 45
utop # sum_matching 9919999;;
- : int = 45
▶ No.831858>>831859
>>831827
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.
▶ No.831859
>>831858
But the versions in >>830756 and >>830760 do and they give the correct output, see >>831834
>>830888 seems to wrap too.
▶ No.831881>>831990
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.
https://play.rust-lang.org/?gist=2092de6b3ca8df308960c83b7073b7c5
Time: 0.04 ms
▶ No.831907>>831914 >>831918
LOL
it's so lame to post spoilers before the thing officially ended
sage
▶ No.831914
▶ No.831918
>>831907
nodev LARPer spotted
antisage btw
▶ No.831943>>831961
Straight and to the point, gets the job done. Only 'clever' part is exploiting properties of complex numbers.
▶ No.831945
▶ No.831961>>831964
>>831943
>complex numbers
Nigga what the fuck? How are complex numbers even remotely necessary here?
▶ No.831964>>831965 >>831985
>>831961
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.
▶ No.831965>>831973
>>831964
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.
▶ No.831973
>>831965
> overengineering
That word doesn't mean what you think it does. They're equivalent.
▶ No.831985>>831986 >>831987
>>831964
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
▶ No.831986>>831987
>>831985
it could be useful in code golf though
▶ No.831987>>831994
>>831985
>because I am sure you're doing it in floating point
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.
> burns CPU
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.
>>831986
> code golf though
Of course.
▶ No.831990>>831993
>>831881
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- https://oeis.org/A141481/b141481.txt | grep -v "^#" | cut -f2 -d' '`; do if [ $row -gt $INPUT ]; then echo $row; break; fi; done
▶ No.831993
>>831990
Part 3 converges to a solution really quickly though, those numbers add up very fast. My one completed in under a millisecond.
> 0.000895 Seconds
▶ No.831994
>>831987
forgot that it's mathematica
Stallman does not approve it
▶ No.832011>>832214
Day 3 is just straight up a math problem not a programming problem.
▶ No.832043
>>831798
Here is your goldstar, you earned it champ
▶ No.832051>>832095
>>831584
c++ was a mistake
▶ No.832095
>>832051
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.
▶ No.832200>>832206
>>831751
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<string_view> 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 << valid;
}
void high_entropy_passphrases2(string input)
{
size_t valid = 0;
for (string_view phrase : input | split([](char c){ return c != '\n'; })){
unordered_set<string> fingerprints;
for (string_view word : phrase | split([](char c){ return !isspace(c); })){
string fingerprint(26, '\0');
for (char letter : word)
++fingerprint[letter - 'a'];
if (auto it = fingerprints.find(fingerprint); it != fingerprints.end())
goto next_phrase;
else
fingerprints.insert(fingerprint);
}
++valid;
next_phrase:;
}
cout << valid;
}
▶ No.832206>>832210
>>832200 (checked)
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) <- s.[i]
done;
Array.fast_sort (fun a b -> if a = b then 0 else if a > b then 1 else -1) a;
a
let 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 (List.map 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 List.map (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.
▶ No.832209>>832211 >>832213
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.
▶ No.832210>>832217
>>832206
too much typing
import re
ws = 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 = 0
for l in lines:
l = tuple(map(lambda x: ''.join(x), map(sorted, l)))
h = set(l)
if len(h) == len(l):
i += 1
print(i)
▶ No.832211
>>832209
the leaderboard system is designed to suck.
just collect your yellow stars m8
▶ No.832213>>832216
>>832209
If I recall the previous years, things do get harder later.
▶ No.832214
▶ No.832216
>>832213
well, then day 4 should have been harder than 3.
maybe it's just one error, I dunno.
▶ No.832217>>832220
>>832210
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.
▶ No.832220>>832221
>>832217
optimization is not needed here though
and when it's needed, Rust > Haskell :)
▶ No.832221>>832222 >>832236 >>832301
>>832220
>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".
▶ No.832222>>832234 >>832368
>>832221
Haskell, from reddit
valid pass = length (nub $ sort pass) == length pass
main = interact $ (++"\n") . show . length . filter valid . map words . lines
part 2:
valid pass = length (nub $ sort $ map sort pass) == length pass
I'd rather deal with golfed perl. Just disgusting.
▶ No.832223
Here's someone doing it with Core (alternate stdlib for OCaml):
open Core
let all_unique_words words =
let set = String.Set.of_list words in
String.Set.length set = List.length words
let sort_chars word =
String.to_list word
|> List.sort ~cmp:Char.compare
|> String.of_char_list
let sort_words words =
List.map words ~f:sort_chars
let no_anagrams = Fn.compose all_unique_words sort_words
let solve () =
let split_words = String.split ~on:' ' in
let passphrases = In_channel.read_lines "./2017/data/4.txt" |> List.map ~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";
▶ No.832225>>832228
Mathematica makes short work of it.
▶ No.832228
>>832225
It can even be golfed shorter, this guy on reddit did it even nicer, hiding my explicit 'True'.
https://www.reddit.com/r/adventofcode/comments/7hf5xb/2017_day_4_solutions/dqqjj88/
▶ No.832234
>>832222
oh yeah, it's the point-less style
▶ No.832236
>>832221
fug, of course it's somethingML.
they look very similar when I haven't written in neither of them for a year.
▶ No.832272>>832274 >>832906
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);
▶ No.832274>>832275
>>832272
explain yourself
trying to smudge your code fingerprint so that you won't get outed as Google Drone #171234 ?
▶ No.832275
>>832274
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.
▶ No.832293>>832300 >>832420
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
);
}
https://play.rust-lang.org/?gist=6380b10c0b0ec10a0b742507b050ca92
Time: 0.52 ms
▶ No.832300>>832319
>>832293
that's some tolerable-looking rust you got right there. eyes aren't bleeding at all. Even so:
>std::time::Instant::now();
not really an improvement over the time() as used by the Greeks and Romans in antiquity
>FastHashSet::default()
if it's the 'default', why do you have to say that?
>INPUT
eyes status: getting a little bit bloodshot
> (d.as_secs() as f64 + d.subsec_nanos() as f64 / 1000000000.0) * 1000.0
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.
▶ No.832301>>832304
>>832221
the virgin haskeller
>thinks functional languages are important
>reads academic programming papers in his spare time just to understand how to write hello world
>purchased a graph theory textbook
>knows what a monad is
>solves programming puzzles for fun
>gives all his variables a type even though the compiler does it automatically
>programs "for the sake of the craft"
THE CHADSNAKE
>writes everything in python because it's the easiest
>thinks "programming paradigms" are for loser nerds
>has never spawned a thread in his life
>takes all his algorithms unashamedly from stack overflow
>first program was an automated trading script, written in half a day, exponential gains everyday
>will never write a line of code for free or for fun
>goes to sleep without thinking about computers
▶ No.832304
>>832301
That's hilarious.
▶ No.832319
>>832300
Thanks for the code review.
▶ No.832368
▶ No.832369
d4p1
(import (srfi srfi-1) (ice-9 rdelim))
(define (valid? str)
(let ((lst (sort (string-split str char-set:blank) string<?)))
(not (any string=? lst (cdr lst)))))
(let loop ((line (read-line)) (count 0))
(if (eof-object? line)
(display count)
(loop (read-line) (+ count (if (valid? line) 1 0)))))
d4p2
(import (srfi srfi-1) (ice-9 rdelim))
(define (sort-string str)
(list->string (sort (string->list str) char<?)))
(define (valid? str)
(let ((lst (sort (map sort-string (string-split str char-set:blank)) string<?)))
(not (or (string-null? str) (any string=? lst (cdr lst))))))
(let loop ((line (read-line)) (count 0))
(if (eof-object? line)
(display count)
(loop (read-line) (+ count (if (valid? line) 1 0)))))
▶ No.832420>>832429 >>832472
>>832293
I optimized it: https://play.rust-lang.org/?gist=e036c920b0c5bc7bfec445cabf2473f9
Time: 0.3 ms
Suck it faggots! Rust is literally the fastest and safest language.
▶ No.832429>>832432
>>832420
>hash with no collision strategy
>fixed max size of 32
>assert that it's fine and then turn the assertions off for 'speed'
just use Forth. it compiles a lot faster.
▶ No.832432>>832436
>>832429
>hash with no collision strategy
It uses linear probing though
▶ No.832436
>>832432
oh. yeah I see it now.
▶ No.832472>>832473 >>832478 >>832540 >>832554
>>832420
fuuuuuuuuuuuuuark
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') <- (hash, v);
ht.len <- ht.len + 1;
true
| (h', v') when h' = hash && v' = v -> false
| (h', v') when h' = hash ->
(* of course this happens if we hash sorted strings
but store the original string... you know what?
let's just pretend legit collisions never happen *)
false
| _ -> loop (i + 1)
in loop 0
let clear ht x =
Array.fill ht.buckets 0 (Array.length ht.buckets) (0, x);
ht.len <- 0
end
let hash_asis = Hashtbl.hash
let hash_sorted s =
let a = Array.make (String.length s) ' ' in
for i = 0 to (String.length s - 1) do
a.(i) <- s.[i]
done;
Array.fast_sort (fun a b -> if a = b then 0 else if a > b then 1 else -1) a;
Hashtbl.hash a
let () =
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 passphrases
built and used as:
$ ocamlopt -O3 unix.cmxa riio.ml -o riio
$ ./riio
Part 1: 337
Part 2: 231
Time: 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.832473>>832522
>>832472
>that syntax highlighting
no serious language uses ' for strings
▶ No.832478
>>832472
>why is it not faster orz
Because Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.
▶ No.832522>>832541
>>832473
>those comments
allaha huakbar
▶ No.832540>>832544
▶ No.832541
>>832522
#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).
>arab mating call
pajeets speak 'english'.
▶ No.832544>>832546
>>832540
>citing the shootout
>in CY+2
on this real world toy problem OCaml and Rust both take no time. That's fine with me.
▶ No.832546>>832550 >>832891
>>832544
actually yours takes more than 1 ms which means you have failed. read the aoc lore. you only have 1 ms for each challenge.
▶ No.832550>>832554
>>832546
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.
▶ No.832554
>>832550
>my laptop can't digitize people.
irrelevant
>I didn't actually compare rust against ocaml directly?
wrong: >>832472 > fuuuuuuuuuuuuuark>why is it not faster orz
>I only have 1TB & 256G disks in this thing.
I don't understand.
>du -h .rustup/toolchains/stable-x86_64-unknown-linux-gnu/
>588M
where is the problem?
▶ No.832839>>832850 >>832889
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()
▶ No.832840>>832876
Not one person has submitted a prolog solution. Aren't there any men around here?
▶ No.832850>>832871 >>832873 >>832889
>>832839
What are you trying to do here?
▶ No.832871>>832873 >>832889
>>832850
in the problem the last number per layer will always be an odd number squared
17 16 15 14 13
18 5 4 3 12
19 6 1 2 11
20 7 8 9 10
21 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.
▶ No.832873>>832889
>>832871
>>832850
i guess i should say shell not layer
▶ No.832876>>832887
>>832840
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: 337
part 2: 231
Time: 0.000000 s
▶ No.832887>>832888
▶ No.832888
▶ No.832889>>832906
>>832873
>>832871
>>832850
>>832839
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())
▶ No.832890>>833433
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<int> 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 << njumps;
}
void twisty_trampolines2(string input)
{
vector<int> 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){
int jump = jumps[i];
if (jump >= 3) --jumps[i]; else ++jumps[i];
i += jump;
}
cout << njumps;
}
▶ No.832891>>832893
>>832546
>you only have 1 ms for each challenge
really?
how would they check that?
▶ No.832893>>832913
>>832891
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.
▶ No.832894>>832904
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 0
let 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) <- n + 1; *)
a.(i) <- n + (if n >= 3 then -1 else 1);
loop i'
end
in loop start
let assemble s =
let rec pop sign num i at start acc =
if i = String.length(s) then (start, sign * num :: acc) else
match s.[i] with
| '-' -> pop (-1) num (i + 1) at start acc
| ')' -> loop (i + 1) (at + 1) start (sign * num :: acc)
| ' ' -> loop (i + 1) (at + 1) start (sign * num :: acc)
| c when c >= '0' && c <= '9' ->
pop sign (num * 10 + int_of_char(c) - int_of_char('0')) (i + 1) at start acc
| _ -> failwith "invalid character in instruction string"
and loop i at start acc =
match s.[i] with
| '(' -> loop (i + 1) at at acc
| ' ' -> loop (i + 1) at start acc
| ')' -> loop (i + 1) at start acc
| _ -> pop 1 0 i at start acc
in
let start, list = loop 0 0 0 [] in
(start, Array.of_list(List.rev(list)))
let steps s =
let start, a = assemble s in
eval start a;
!inst_count
also totally pointless 'find out where we're to start' code, looking for parenthesized numbers in input.
▶ No.832904
>>832894
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
▶ No.832906
>>832889
I've already done it here:
>>832272
▶ No.832913
>>832893
Actually it is 25 ms before christmas. You have 1ms for both path parts.
▶ No.832955>>832961 >>833615
fn main() {
let instant = std::time::Instant::now();
let ops: Vec<i32> = 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
}
https://play.rust-lang.org/?gist=c48827dcbf01fb0efa5acbfe7442303e
Time: 83 ms
I fucking blew it. I ruined Christmas.
▶ No.832961
>>832955
I guess all that safety comes at a price :^)
▶ No.832962>>832965
Mathematica.
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!
▶ No.832965
>>832962
>After 45 seconds I still didn't have an answer for part2
damn
▶ No.832982>>832987 >>833317
Pretty substantial drop off from day 2 to 3.
▶ No.832987>>833035
>>832982
Can you hear that? It's the sound of over 9000 Pajeets vanishing.
▶ No.833035>>833317
>>832987
day 5 was pretty easy. not a shock like day 3 was. it's probably just Monday night and people having jobs.
▶ No.833102>>833105 >>833115
Day 5 in Rust: https://play.rust-lang.org/?gist=7b0b5ddc9fa74443e2257f80108d63df&version=stable
use std::fs::File;
use std::io::{BufReader, BufRead};
fn part1(mut jumps: Vec<i32>) -> 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<i32>) -> 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<i32> = vec![];
for line in BufReader::new(file).lines() {
jumps.push(line.unwrap().parse::<i32>().unwrap());
}
println!("{}", part1(jumps.clone()));
println!("{}", part2(jumps.clone()));
}
Takes about 3 seconds.
▶ No.833105
>>833102
Forgot to use --release, now it runs in about 100ms.
▶ No.833115>>833118 >>833193
>>833102
Not awful but still pretty bad.
>File::open("input")
read from stdin and pipe input into it
>manually collecting into a collection
use Iterator::collect
>parse::<i32>()
you already have said that you want i32. no need to use the ugly turbofish syntax.
>part1 and part2
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].
>doing bounds checking multiple times
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<i32> = 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
}
▶ No.833118>>833119
>>833115
Thank you for your feedback. I've seen your post but only after I posted my solution.
>also there is no need to give thos functions a vec. just give them a &mut [i32].
We both call .clone() on a Vec<i32>, which returns a Vec<i32> but gets casted (?) to a &mut [i32] without actually changing any data. Or is there any difference?
▶ No.833119
>>833118
No there really isn't a difference. I was just nitpicking.
▶ No.833124
Scrub tier perl solutions for day5
use strict;
use warnings "all";
my @data;
while (<DATA>) {
push(@data, $_);
}
my $size = int @data;
my $index = 0;
my $jumps = 0;
for (;;) {
$index += $data[$index]++;
++$jumps;
if ($index > $#data) {
die "$jumps\n";
}
}
__DATA__
0
3
0
1
-3
use strict;
use warnings "all";
my @data;
while (<DATA>) {
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__
0
3
0
1
-3
▶ No.833131>>833188
Ungolfed Perl6:
my $i = 0;
my $res= 0;
my $instr = lines.map(+*).Array;
while ($i < $instr.elems) {
$i += $instr[$i] >= 3 ?? $instr[$i]-- !! $instr[$i]++;
$res++;
}
$res.say
~ $ time perl6 dik.pl6 < input
23948711
real 1m40.691s
user 1m40.647s
sys 0m0.037s
Compared to my Rust version thats pretty much the one Steve Klabnik posted:
~ $ time ./dik < input
23948711
real 0m0.054s
user 0m0.051s
sys 0m0.003s
Perl6 truly is the future of computing.
▶ No.833160
push@_,$_ while<>;$i+=$_[$i]>=3?$_[$i]--:$_[$i]++while$i<~~@_&&++$a;print$a.$/
~ $ time perl dik.pl < input
23948711
real 3.35s
user 3.34s
sys 0.00s
▶ No.833188
>>833131
rip perl6, we hardly knew ya
▶ No.833190>>833193
>all these implementations that only check for i < arraysize
fug did I imagine that requirement as well?
<The goal is to follow the jumps until one leads outside the list.
nope, that's pretty clear. i < 0 is also outside the array. this contest just doesn't demand much of what it says it does.
▶ No.833193
>>833190
In my solution >>833115 i is a signed integer that I cast to an unsigned one. Thanks to the awesomness of two's complement this just werks.
▶ No.833262>>833266 >>833300 >>833334
Did almost all of them in python but stuck on puzzle 3. Any hints? pls no spoilers
▶ No.833266>>833334
>>833262
You either generate the spiral and keep track of two coordinates, or you just work it out with math.
▶ No.833300
>>833262
an easy way to do the spiral in python would be to use 2d coordinates as dictionary keys
▶ No.833317
>>833035
>>832982
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.
▶ No.833326
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.
▶ No.833334>>833390
>>833262
>>833266
You could also do recursion, like one of the R*st solutions in this thread. Hint: don't.
▶ No.833390>>833394
>>833334
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?
▶ No.833394
>>833390
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.
▶ No.833431
d5
(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)))
▶ No.833433>>833435 >>833439
>>832890
What language is this?
▶ No.833435
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<string> 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 << ncycles;
}
void memory_reallocation2(string input)
{
string mem;
for (int val : input | split(by_word) | map_to(to_int))
mem.push_back(val);
unordered_map<string, size_t> seen;
size_t ncycles = 0;
for (; !seen.count(mem); ++ncycles){
seen.emplace(mem, ncycles);
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 << ncycles - seen[mem];
}
>>833433
Just good old C++.
▶ No.833439
▶ No.833450>>833451
wtf does part 2 of day 6 even mean?
▶ No.833451>>833452 >>833453
>>833450
god fucking damnit it's asking the same exact question again and expecting a different answer.
▶ No.833452
>>833451
close, but not exactly
▶ No.833453
>>833451
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"
▶ No.833454>>833500
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) <- 0;
let rec loop j rest =
a.(j) <- a.(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
let max_block a =
let max, maxi = ref a.(0), ref 0 in
for i = 1 to Array.length a - 1 do
if a.(i) > !max then (max := a.(i); maxi := i)
done; !maxi
let smooth a =
let seen = Hashtbl.create (Array.length a) in
let wtf a = String.concat ":" (Array.fold_left (fun acc n -> 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
▶ No.833467>>833529
d6
(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)))))
▶ No.833473>>833475
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?
▶ No.833475
>>833473
nevermind, I misunderstood the question
▶ No.833491>>833492
Day 6 in Rust: https://play.rust-lang.org/?gist=6cdb06cdd8dfa521045f5054d1cf2223&version=stable
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().
▶ No.833492>>833495 >>833496
▶ No.833495>>833496
>>833492
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.
▶ No.833496
>>833492
>>833495
Like this:
const arr: [u32; 3] = [1,2,3];
fn test(x: [u32; arr.len()]) {
println!("{:?}", x);
}
fn main() {
test(arr);
}
▶ No.833500
>>833454
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;
!maxi
let 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
▶ No.833502
rare instance found of actually readable Haskell
naturally the author posted it with a sincere apology. that community is fucked
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import Data.Set (Set)
import qualified Data.Set as Set
import Data.List
distribute :: Int -> Int -> Seq Int -> Seq Int
distribute 0 _ banks = banks
distribute remaining currentIndex banks = distribute newRemaining newIndex newBanks
where newRemaining = remaining - 1
newIndex = mod (currentIndex + 1) (length banks)
newBanks = Seq.adjust (+1) currentIndex banks
doCycle :: Seq Int -> Seq Int
doCycle 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 banks
getFirstRepeatedConfig :: 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 prevConfigs
getTimeToCycle :: Int -> Seq Int -> Seq Int -> Int
getTimeToCycle count banks targetConfig
| banks == targetConfig = count
| otherwise = getTimeToCycle newCount newBanks targetConfig
where newCount = count + 1
newBanks = doCycle banks
main :: IO ()
main = do
contents <- readFile "../input.txt"
let banks = Seq.fromList $ map read $ words contents
let (cycleTime, banksAfter) = getFirstRepeatedConfig 0 banks Set.empty
let timeToNextCycle = getTimeToCycle 1 (doCycle banksAfter) (banksAfter)
putStrLn $ "Solution 1:" ++ (show cycleTime)
putStrLn $ "Solution 2:" ++ (show timeToNextCycle)
▶ No.833529
>>833467
(((functional programming)))
▶ No.833532
perl is perlfect for challenges because it lets you do anything even if its retarded beyond belief
▶ No.833534>>833536 >>833544 >>833547
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.
▶ No.833536>>833537
>>833534
You don't need to????
▶ No.833537>>833538
▶ No.833538>>833539
>>833537
Take your autism and leave
▶ No.833539
▶ No.833544>>833546
>>833534
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.
▶ No.833546>>833743 >>833942
>>833544
>binary tree
too slow
>SIMD
llvm already does that for me
▶ No.833547
>>833534
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.
▶ No.833551>>833558
▶ No.833558>>833604
>>833551
Hmm if I run it 1000 times and take the average time it is <1ms. I'll take. Christmas is saved!!!
https://play.rust-lang.org/?gist=a20ae380e856126347b419f65743373f&version=nightly&mode=release
Time: 0.9 ms
▶ No.833604>>833615
>>833558
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.
▶ No.833615>>833624
>>833604
Every day except 5 runs under 1ms. Day 5 takes 83 ms: >>832955
>You should link all your solutions together
I'm doing that. Right now it is a mess though. Once I've cleaned it up I'll make a ShitHub repo.
▶ No.833624
>>833615
Ahh, day 5 is going to make it rather untenable then. And who knows what length solutions lie ahead.
▶ No.833633>>833639 >>834115
/**
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
struct pos {
int item, index;
};
void
print_banks(int *banks, int blen) {
printf("[");
for (int i = 0; i < blen; i++)
printf("%d, ", banks[i]);
printf("\b\b] \n");
}
int
next_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;
}
void
push_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;
}
void
push_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;
}
int
steps_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 pos
pop_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};
}
int
main(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 <= pos.item; i++) {
banks[(i + pos.index) % blen]++;
}
}
if (part == 1) fprintf(stderr, "Total steps: %d\n", slen);
else fprintf(stderr, "Steps between repeats: %d\n", slen - repeat);
return 0;
}
m712@nextchan:~$ gcc -o day6 day6.c -O3 -ffast-math -funroll-loops -ftree-vectorize -Wall -Wextra -Werror -pedantic -std=c99
m712@nextchan:~$ time ./day6 1 < day6input >/dev/null
Total steps: 4074
real 0m0.044s
user 0m0.041s
sys 0m0.002s
>45ms
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.
▶ No.833639>>833647 >>833648 >>834570
>>833633
WEEEEEEEEEEEEEEEEEEEEEEEEW LAD
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?
▶ No.833647
>>833639
verbose?
It's perfectly normal C.
Stylistically, C is all downhill from here, especially as it's ported.
▶ No.833648>>833650 >>833653
>>833639
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.
▶ No.833650
>>833648
>128 bytes
Brain melt, i meant 16 ints.
▶ No.833653>>833662
>>833648
>C doesn't have that big of an stdlib
Then stop using C tbh
>I read ints from stdin and parse it, while your input is embedded.
Changing it to read from stdin wouldn't change the LOC of my Rust solution.
>while mine is generic and its limits are your computer's RAM limits
The challenge states that there are only 16 memory banks
I rate you pajeet/10
▶ No.833662>>833663 >>833664
>>833653
>Then stop using C tbh
no u
>Changing it to read from stdin wouldn't change the LOC of my Rust solution.
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.
>The challenge states that there are only 16 memory banks
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 pajeet/10
I rate you "not an argument"/10.
▶ No.833663
▶ No.833664>>833672
>>833662
>This matters in real world development
This is a fucking challenge. Holy shit stop LARPing.
>which these series of code challenges are trying to educate you about.
https://en.wikipedia.org/wiki/Advent_calendar
▶ No.833672>>833676
>>833664
>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.
>https://en.wikipedia.org/wiki/Advent_calendar
And?
▶ No.833674>>833919
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.
▶ No.833676
>>833672
>Keep that mindset, Pajeet.
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".
>And?
It isn't meant to "educate" about "real world development". It is meant to be a fun little challenge every day until christmas.
https://adventofcode.com/2017/about
>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.
▶ No.833743>>833768 >>833942
>>833546
>>binary tree
>too slow
Actually no, depending on input it runs well below 1ms:
#include <stdio.h>
#include <alloca.h>
#include <string.h>
#include <stdint.h>
#include <sys/time.h>
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(history.data, INPUT, 16);
history.left = NULL;
history.right = NULL;
history.step = 0;
unsigned int ctr = 0;
unsigned int size;
unsigned char *curdata = history.data;
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;
}
▶ No.833768>>833775
>>833743
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.
▶ No.833775
>>833768
On my machine:
>Part 1: 12841
>Part 2: 8038
>Time: 2553 us
But yeah it's not optimal. With the input from >>833471 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.
▶ No.833919
>>833674
>u guys r 2 srs
>ALL THE TOP RATED GUYS THEY SAY
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.
▶ No.833942
>>833546
>>833743
>>>binary tree
You could try a bloom filter.
▶ No.833979>>833987
Finally day 7 required a bit of thinking to get through.
Still, it's mostly brute force.
import re
from collections import defaultdict
pt = 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, other
all = set()
not_bottom = set()
class P:
def __init__(self):
self.name = None
self.weight = None
self.parent = None
self.children = None
all_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]
bp.name = 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(root.name)
def 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 + diff
print(check_weight(root))
▶ No.833987
>>833979
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.
▶ No.833992>>833993 >>834443
day 7. phew.
void recursive_circus1(string input)
{
unordered_set<string_view> 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 << *has_no_base.begin();
}
struct node_t { vector<node_t*> next; int weight, total_weight; };
int needed_weight(node_t* parent)
{
parent->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<string_view, node_t> tree;
unordered_set<string_view> 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<node_t*>& next = node.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 << needed_weight(&tree[*has_no_base.begin()]);
}
New helper functions:
template<typename P> constexpr auto grab_while(string_view in, P&& p)
{
if (in.empty()) return pair(string_view(), string_view());
size_t cur = 0;
if (p(in[cur])) do ++cur; while(cur < in.size() && p(in[cur]));
return pair(string_view(in.data(), cur), string_view(in.data() + cur, in.size() - cur));
}
bool by_alpha(char c) { return isalpha(c); }
bool by_num(char c) { return isdigit(c); }
▶ No.833993>>833996
>>833992
wow
is it C++18? or what version?
last time I saw any C++ code it didn't look like that.
▶ No.833995
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 # List.map (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 # List.map (fun x -> total_weight [x]) (Hashtbl.find claims "ghwgd");;
- : int list list = [[274]; [274]; [274]]
utop # Hashtbl.find names "ghwgd";;
- : int = 370
utop # 274 * 3 + 370;;
- : int = 1192
utop # 1184 - 274 * 3;;
- : int = 362
▶ No.833996>>833999
>>833993
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: >>831584 (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.
▶ No.833999>>834007
>>833996
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++?
▶ No.834006>>834016
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.
▶ No.834007
>>833999
>then how would you write the solution if you were not allowed to use templates beyond simple parametric polymorphism (like in Java or Haskell)?
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 >>831584 , I'm using a type trait in one place, but that's it. If you mean without any of >>831584 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).
>and in general is C++ worth learning now that it got all this cool stuff?
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.
>especially with regard to difficulty of writing code that doesn't corrupt memory.
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.).
>or I'd better create a designated thread for the discussion of modern C++?
If this conversation gets too large, I guess.
▶ No.834011>>834015
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)
▶ No.834013>>834115
#!/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 <http://www.gnu.org/licenses/>.
import sys
import re
import collections
class Tree(object):
def __init__(self, name, weight, children):
self.name = name
self.weight = weight
self.children = children
self.parent = None
def __repr__(self):
return "<{:s}: {:s}>".format(type(self).__name__, str(self))
def __str__(self):
return "{:s} ({:d}) -> {:d} children".format(self.name, 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(sys.stdin.read())
print('Top of tree:', part1(trees).name)
print('Correct value:', part2(part1(trees)))
m712@nextchan:~$ time python3 day7.py <day7input >/dev/null
real 0m0.095s
user 0m0.072s
sys 0m0.008s
C version coming after the Py3 implementation.
▶ No.834015>>834016 >>834258
>>834011
Pajeets having trouble traversing a tree
▶ No.834016
>>834006
>amortized
Ugh I meant memoized
>>834015
They're just waiting for the Java solution to be posted on reddit so they can copy+paste into Eclipse.
▶ No.834112>>834114 >>834115 >>834540
/**
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
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)) \
<< (5 * hi); \
} while (0)
char *
get_word(void) {
char *str = NULL;
int len = 0;
int c;
while (isalnum((c = getchar())))
PUSH(char *, str, len, c);
PUSH(char *, str, len, 0);
ungetc(c, stdin);
return str;
}
int
get_int(void) {
int val = 0;
int c;
while (isdigit((c = getchar()))) {
val = 10*val + (c - '0');
}
ungetc(c, stdin);
return val;
}
static int line;
Node *
node_from_line() {
line++;
// name (weight) -> 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;
}
1/3
▶ No.834113>>834114
void
resolve_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);
}
}
int
calc_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;
void
get_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);
}
}
int
part2(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];
}
}
int
main(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@ion ~ % time ./day7 1 < day7input
Name of root: vvsvez
./day7 1 < day7input 0.00s user 0.00s system 97% cpu 0.007 total
m712@ion ~ % time ./day7 2 < day7input
Required weight: 362
./day7 2 < day7input 0.01s user 0.00s system 96% cpu 0.007 total
2/2
>7ms
F
Valgrind shows no leaks. This time I used a hashmap.
▶ No.834114
>>834112
>>834113
Don't you know what a pastebin is?
▶ No.834115>>834116
>>833633
>>834013
>>834112
>GPL header
Made me smile
▶ No.834116>>834125
>>834115
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.
▶ No.834125>>834127
>>834116
Do you want me to modify and study your comment?
▶ No.834127
>>834125
As long as you preserve my copyright notice and the license notice, you are permitted to modify everything.
▶ No.834169>>834175 >>834181
>rustfag still hasn't posted
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
▶ No.834175>>834181 >>834452
>>834169
>>rustfag still hasn't posted
Yeah my solution is beyond pajeet level (also I have accidentally deleted it). I'm rewriting it currently.
>LOL @ language that doesn't allow doubly linked lists
https://doc.rust-lang.org/std/collections/struct.LinkedList.html
How is this relevant to this challenge?
>LOL @ language can't have trees with parents
Why would you ever do that? Also, how is this relevant to the challenge?
>LOL @ safety from using it for anything but toy projects
https://en.wikipedia.org/wiki/Rust_(programming_language)#Projects_using_Rust
▶ No.834181>>834190
>>834169
>>834175
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<String>,
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::<u32>().unwrap(),
});
} else {
tree.get_mut(&c[1]).unwrap().weight = c[2].parse::<u32>().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;
}
}
}
▶ No.834190>>834201
>>834181
> fuck the borrow checker
Isn't that Rust's greatest ally?
▶ No.834201
>>834190
It's what is supposed to make Rust safe. It is also the reason why Pajeets will never be able to write Rust.
▶ No.834203>>834204 >>834246
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).
▶ No.834204
>>834203
Should have been 42 minutes, was distracted before hitting send.
▶ No.834246>>834284
>>834203
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.
▶ No.834258>>834262
>>834015
>coders
>guys in the background clearly not doing coding
well done
▶ No.834262
>>834258
>>guys in the background clearly not doing coding
But the guys in the front are.
Prove me wrong.
▶ No.834272>>834275 >>834285 >>834452
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<String>,
weight: u32,
}
fn get_children<'a>(tree: &'a HashMap<String, Program>, node: &'a str) -> Vec<String> {
let mut result = vec![];
for x in tree.iter().filter(|&i| i.1.parent == Some(node.to_string())) {
result.push(x.0.clone());
}
result
}
fn get_weight(tree: &HashMap<String, Program>, node: &str) -> u32 {
get_children(tree, node).iter().fold(tree.get(node).unwrap().weight, |acc, x| acc + get_weight(tree, x))
}
fn get_parent(tree: &HashMap<String, Program>, node: &str) -> String {
let x = tree.get(node).unwrap();
let x = x.parent.clone();
x.unwrap()
}
fn find_unbalanced<'a>(tree: &'a HashMap<String, Program>, node: &'a str) -> String {
let mut x = get_children(tree, node).iter().map(|x| (x.clone(), get_weight(tree, &x))).collect::<Vec<(String, u32)>>();
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::<u32>().unwrap(),
});
} else {
tree.get_mut(&c[1]).unwrap().weight = c[2].parse::<u32>().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::<Vec<(&String, u32)>>();
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));
}
}
▶ No.834275
>>834272
this is worse than c++
▶ No.834284>>834288
>>834246
>stats aren’t interesting
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.
▶ No.834285>>834291
>>834272
>all these fucking ".unwrap()" everywhere
Very memory-safe :^)
>iterating through a hash map and filtering on names to find a node's children
Just use pointers, man.
▶ No.834288>>834291 >>834328
>>834284
>day 3 is difficult
>day 4 and 5 are easy
>relatively harder problems
you're retarded, people are busy writing code for money instead of wasting time doing shit for free
▶ No.834291>>834301 >>834304
>>834285
>Very memory-safe :^)
Yes because it just crashes if .unwrap() fails
>Just use pointers, man.
No, that would be unsafe.
>>834288
As if your neet time was worth anything
▶ No.834301
>>834291
what does my time have to do with other people working?
▶ No.834304
>>834291
>loading up code with dumb syntax noise is the right way to assuage my memory-safety paranoia
t. delusional fanatic
>Who cares about performance? Muh safety!
Might as well use a garbage-collected language.
▶ No.834328
>>834288
> instead of wasting time doing shit for free
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.
▶ No.834438>>834452
Cheating with eval
import re
from collections import defaultdict
ws = 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 = 0
with 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)
▶ No.834440>>834441
Day 8 Golfed
203 characters
import collections as C
v=C.defaultdict(int)
m=0
for 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)
▶ No.834441>>834444
>>834440
200 characters
ditched 'if' statement because I can implicitly convert bool to int
import collections as C
v=C.defaultdict(int)
m=0
for 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)
▶ No.834443>>834463
>>833992
day 8. Nothing fancy.
void heard_you_like_registers(string input)
{
unordered_map<string_view, int> reg;
auto compare = [](int a, string_view op, int b){
return op == "==" ? a == b : op == "!=" ? a != b :
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 << "part 1: " << max_element(reg.begin(), reg.end(), [](auto&& a, auto&& b){ return a.second < b.second; })->second << '\n';
cout << "part 2: " << highest << '\n';
}
New helper functions for today, building on previously made grab_while to parse multiple things:
template<typename... Ps, size_t... n> constexpr auto parse_only_impl(index_sequence<n...>, string_view in, Ps&&... ps)
{
array<string_view, sizeof...(ps) + 1> res;
((tie(res[n], in) = grab_while(in, not_fn(forward<decltype(ps)>(ps))),
tie(res[n], in) = grab_while(in, forward<decltype(ps)>(ps))), ...);
res[sizeof...(ps)] = in;
return res;
}
template<typename... Ps> constexpr auto parse_only(string_view in, Ps&&... ps)
{
return parse_only_impl(index_sequence_for<Ps...>{}, in, forward<Ps>(ps)...);
}
bool by_int(char c) { return isdigit(c) || c == '-'; }
▶ No.834444>>834576
>>834441
197 characters
no need to compare strings by equality here :D
import collections as C
v=C.defaultdict(int)
m=0
for 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)
▶ No.834452>>834453 >>834517
#!/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 <http://www.gnu.org/licenses/>.
import sys
def 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,
">=": 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(sys.stdin.read()))
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.
>>834272
>all those duplicate strings
>.unwrap() a million times
>while let Some(ref x) = tree.get(ptr).unwrap().parent
>iterating over the tree to get the parent
BEYOND WORDS
>>834175
>Why would you ever do that? Also, how is this relevant to the challenge?
>why would you use a thing that makes part 1 O(log(n))
>>834438
>Cheating with eval
Cheating is for niggers.
▶ No.834453
▶ No.834460>>834464
Mathematica. This is a simple one for any language with first class functions.
▶ No.834463>>834466 >>834979
>>834443
Slightly modified to make comparison more efficient and use a more appropriate parsing function:
void heard_you_like_registers(string input)
{
unordered_map<string_view, int> reg;
auto compare = [](int a, string_view op, int b){
return op[0] == '=' ? a == b :
op[0] == '!' ? a != b :
op[0] == '<' ? (op.size() == 1 ? a < b : a <= b) :
(op.size() == 1 ? a > b : a >= b);
};
int highest = int((~0u >> 1) + 1);
for (string_view line : input | split(by_line)){
auto [modif, ins, val, if_, compreg, comp, compval, rest] = parse_n<7>(line, by_word);
if (compare(reg[compreg], comp, stoi(string(compval))))
if (int cur = reg[modif] += stoi(string(val)) * (ins == "inc" ? 1 : -1); cur > highest)
highest = cur;
}
cout << "part 1: " << max_element(reg.begin(), reg.end(), [](auto&& a, auto&& b){ return a.second < b.second; })->second << '\n';
cout << "part 2: " << highest << '\n';
}
parse_n:
template<typename P, size_t... n> constexpr auto parse_n_impl(index_sequence<n...>, string_view in, P&& p)
{
array<string_view, sizeof...(n) + 1> res;
((tie(res[n], in) = grab_while(in, not_fn(p)),
tie(res[n], in) = grab_while(in, p)), ...);
res[sizeof...(n)] = in;
return res;
}
template<size_t n, typename P> constexpr auto parse_n(string_view in, P&& p)
{
return parse_n_impl(make_index_sequence<n>{}, in, forward<P>(p));
}
▶ No.834464>>834473 >>834488
>>834460
Still longer than Python with 197 characters.
▶ No.834466>>834470
>>834463
I guess I can also replace the
ins == "inc"
with
ins[0] == 'i'
, while I'm at it.
▶ No.834470>>834475
>>834466
It would be longer by 1 character if you don't count removable whitespace.
▶ No.834473
>>834464
And I didn't get quads either, but such is life.
▶ No.834475>>834476
>>834470
I was more going for efficiency than code length for that one, though.
▶ No.834476>>834478
>>834475
It is irrelevant here. Even python solution finishes in a blink of an eye or faster.
That's autism.
▶ No.834477>>834480 >>834538
Wtf I love Rust now https://play.rust-lang.org/?gist=7487acd162ae615a85dca98654c2d889&version=stable
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<String, i32> = 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::<i32>().unwrap(),
"!=" => *registers.get(&c[4]).unwrap_or(&0) != c[6].parse::<i32>().unwrap(),
"<=" => *registers.get(&c[4]).unwrap_or(&0) <= c[6].parse::<i32>().unwrap(),
">=" => *registers.get(&c[4]).unwrap_or(&0) >= c[6].parse::<i32>().unwrap(),
"<" => *registers.get(&c[4]).unwrap_or(&0) < c[6].parse::<i32>().unwrap(),
">" => *registers.get(&c[4]).unwrap_or(&0) > c[6].parse::<i32>().unwrap(),
_ => panic!(),
} {
let r = registers.entry(String::from(&c[1])).or_insert(0);
match &c[2] {
"inc" => *r += c[3].parse::<i32>().unwrap(),
"dec" => *r -= c[3].parse::<i32>().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));
}
▶ No.834478>>834479
>>834476
You know what's also autistic?
<It would be longer by 1 character if you don't count removable whitespace.
My flavor of autism is better than yours.
▶ No.834479>>834481
>>834478
Code golf is a legitimate thing btw.
▶ No.834480>>834487
>>834477
Show us the day 7 solution in Rust which is not ugly as fuck.
▶ No.834481
>>834479
And so is optimization tbh fam.
▶ No.834487>>834493 >>834578
>>834480
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<&str> = line.split(' ').collect();
let a = *registers.get(c[4]).unwrap_or(&0);
let b = c[6].parse::<i32>().unwrap();
let d = c[2].parse::<i32>().unwrap();
if match c[5] {
"==" => a == b,
"!=" => a != b,
"<=" => 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);
}
▶ No.834488>>834505
>>834464
Haven't golfed variable names, but getting smaller...
▶ No.834493>>834495
▶ No.834495
>>834493
Oh right. No. Maybe Steve will.
▶ No.834505
>>834488
A bit smaller removing that switch. Forgive me, but also posted this version on reddit.
▶ No.834517>>834534 >>834576
>>834452
>filter(lambda x: x, input.split('\n'))
Why don't you just input.splitlines()?
▶ No.834534
>>834517
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"]
▶ No.834535>>834577
Day 7: https://play.rust-lang.org/?gist=cba1239b4aa56b484c607c61e7a6b637
Time: 0.86 ms
>inb4 Rc<RefCell<Program>>
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: https://play.rust-lang.org/?gist=20bb760159cbd1ff5d5479c96f52c6e1
Time: 0.38 ms
Pretty verbose. I'm probably going to make it shorter later today.
▶ No.834538>>834540 >>834547
>>834477
m712@warp ~ % grep unwrap day8.rs | wc -l
13
▶ No.834540>>834545 >>834564
>>834538
>muh LOC
LOL. >>834112 >>834113
stfu you stupid turkoachh
▶ No.834545>>834564
>>834540
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.
▶ No.834547>>834564
>>834538
grep unwrap >>834487 | wc -l
6
So? Would you rather prefer undefined behavior?
▶ No.834564>>834565 >>834566 >>834567 >>834578 >>834587
>>834540
>stfu you stupid turkoachh
>oachh
Please, it's turkroach.
>>834545
>How is this worse than using Exceptions for control flow? Kill yourself retarded python nigger.
match &c[5] {
"==" => *registers.get(&c[4]).unwrap_or(&0) == c[6].parse::<i32>().unwrap(),
"!=" => *registers.get(&c[4]).unwrap_or(&0) != c[6].parse::<i32>().unwrap(),
"<=" => *registers.get(&c[4]).unwrap_or(&0) <= c[6].parse::<i32>().unwrap(),
">=" => *registers.get(&c[4]).unwrap_or(&0) >= c[6].parse::<i32>().unwrap(),
"<" => *registers.get(&c[4]).unwrap_or(&0) < c[6].parse::<i32>().unwrap(),
">" => *registers.get(&c[4]).unwrap_or(&0) > c[6].parse::<i32>().unwrap(),
_ => panic!(),
}
comps = {
"<": lambda a,b: a<b,
">": lambda a,b: a>b,
"==": 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.
>>834547
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.
▶ No.834565>>834567
>>834564
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
▶ No.834566>>834568 >>834570
>>834564
>oh look. a good thread on /tech/
>lets go into it and post pajeet supreme solutions so long that i have to split them up
>oh look. rust code.
>MUH UNWRAP
the moment you posted in this thread it turned to shit. fuck off turkroach
▶ No.834567>>834569 >>834575 >>834578
>>834564
>>834565
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
▶ No.834568
>>834566
>good thread
>shilling for some reddit "puzzle" crap
lmfao
▶ No.834569>>834571
>>834567
>reference counting
as i said: pajeet
polite sage. im going to stop engaging you now.
▶ No.834570
>>834566
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 >>833639 and started shitposting.
▶ No.834571>>834603
>>834569
>refcounting is bad
pic related
Give one argument against it.
▶ No.834575
>>834567
>interpreted languages
>Use reference counting
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.
▶ No.834576
>>834517
why use splitlines at all if you can simply iterate the file like in >>834444
?
▶ No.834577
>>834535
> Rc<RefCell<…
lol
▶ No.834578>>834581
>>834564
>>834567
Please see my updated solution in >>834487. None of the unwraps is used to solve a problem that could be solved using reference counting.
>let file = File::open("input").unwrap();
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.
>let line = line.unwrap();
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.
>let a = *registers.get(c[4]).unwrap_or(&0);
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::<i32>().unwrap();
>let d = c[2].parse::<i32>().unwrap();
Again, no exceptions. parse gives an `Option` which contains the result, an i32, or None.
>println!("Part 1: {}", registers.values().max().unwrap());
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.
▶ No.834581
>>834578
<No exceptions? This sucks!
Languages that do have exceptions basically do the same except they return what would be called a Result<T, E> (T is the type of the return value and E is the type of an exception) in Rust, and automatically unwrap() the T if there is one, or pass the E up the stack until it is caught.
▶ No.834587
>>834564
Also
>favoring lambdas and dict lookups over my sick `if match`
▶ No.834597>>834687
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) => {(
$iter.next().unwrap(),
$iter.next().unwrap(),
$iter.next().unwrap().parse::<i32>().unwrap()
)}
}
let (l1, op1, r1) = parse!(iter);
iter.next();
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
▶ No.834602
day 8 was fun. ocaml:
type modop = Inc | Dec
type condop = Gt | Ge | Eq | Ne | Lt | Le
type 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) <= n
| Lt -> (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
▶ No.834603
▶ No.834687>>834688
>>834597
>unwrap
>beautiful
▶ No.834688>>834690 >>834699
>>834687
>hurr durr
>XDDDDDD
not an argument
▶ No.834690>>834691
>>834688
No need to be so rusty friendo
▶ No.834692
>>834691
>rust is being discussed
>link python
▶ No.834699>>834703 >>834707
>>834688
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"));
// ...
int sock;
CHECK_NZERO(getaddrinfo(...));
// ...
CHECK_LTZERO(sock = socket(domain, type, protocol));
CHECK_LTZERO(connect(sock, "8ch.net", 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?
▶ No.834703
>>834699
>Would Rustfagsdevs consider adding ? functions for returning an Option and exploding by default?
Added in v1.22
https://blog.rust-lang.org/2017/11/22/Rust-1.22.html
>The headline feature for this release is one many have been anticipating for a long time: you can now use ? with Option<T>! About a year ago, in Rust 1.13, we introduced the ? operator for working with Result<T, E>. 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<T>?
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.
▶ No.834705>>834732 >>834740
>>834691
>turkroach
>implying I'd post smug anime
This is your brain on delusion.
▶ No.834707>>834710
>>834699
also File::open returns a Result not an Option
▶ No.834710>>834712
>>834707
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")
.
▶ No.834712>>834714 >>834752
>>834710
that is absolutely awful though. why would you want to crash your program?
▶ No.834714>>834716
>>834712
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.
▶ No.834716>>834770
>>834714
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.
▶ No.834721>>834764
>be anti rust shill
>hurr muh unwrap
>see this:
https://play.rust-lang.org/?gist=4f59385d7ea3cae44be11499cd1c25d2
>ctrl + f unwrap
>0 matches
>kill self
▶ No.834752>>834755
>>834712
>why would you want to crash your program
go away from programming until it's too late.
people like you created fucking PHP and Javascript.
▶ No.834755
>>834752
>go away from programming until it's too late.
so after it is too late i can come back?
LOL. learn 2 english, kiddo.
▶ No.834760
>>834740
>i am now imkampfy
ok
▶ No.834764
>>834721
>replace .unwrap() with Result op* which unwraps anyway
>replace .unwrap() with .ok()
wow you sure convinced me
▶ No.834770>>834825
>>834716
>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.
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 ?.
>(Rust is all about being explicit btw)
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.
▶ No.834825>>834827
>>834770
>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.
▶ No.834827>>834839
>>834825
>in fact it is discouraged to do that in real world code.
they why does every rust code in this thread have copious amounts of unwrap in it?
▶ No.834839
>>834827
because it isnt real world code? because as long as the input isnt bad it wont panic? because even if it panics nobody cares?
▶ No.834979>>834982 >>835014
>>834463
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 garbage;
goto epilogue;
garbage:
for (input.remove_prefix(1); !input.empty(); input.remove_prefix(1))
if (input[0] == '!') input.remove_prefix(1);
else if (input[0] == '>') goto not_garbage;
else ++garbage_count;
epilogue:
cout << "part 1: " << score << '\n';
cout << "part 2: " << garbage_count << '\n';
}
▶ No.834982
>>834979
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.
▶ No.834985>>835052
183 characters
too lazy to golf it further, I think it must be possible but fuck it.
import re
t=re.sub('!.','',open('i','r').read())
g=re.compile('<.*?>')
s=0
l=0
for c in g.sub('',t):
if c=='{':l+=1
elif c=='}':s+=l;l-=1
print(s,sum(len(x)-2for x in g.findall(t)))
▶ No.835011
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
| '<' -> garbage (i + 1) (fun i -> group i parens score)
| '{' -> group (i + 1) (parens + 1) (score + parens + 1)
| '}' -> if parens = 1 then (scores := !scores + score; loop (i + 1)) else
group (i + 1) (parens - 1) score
| c -> group (i + 1) parens score
and loop i =
if i = len then !scores, !gc else
match s.[i] with
| '!' -> loop (i + 2)
| '<' -> garbage (i + 1) (fun i -> loop i)
| '{' -> group (i + 1) 1 1
| c -> failwith (sprintf "unexpected character in loop %d: %c" i c)
in loop 0
▶ No.835014>>835023
>>834979
>goto
>not mutually recursive functions
damn, I missed that ! only shows up in garbage
▶ No.835023
>>835014
>mutually recursive functions
Wouldn't have looked much better. Also, I don't know if GCC would have been able to optimize it into something as efficient.
▶ No.835037>>835067
More hard challenges will be released on the
12th
18th
25th
respectively.
The other days are normal/easy challenges.
▶ No.835052>>835056
>>834985
Good job.
Why has this thread been silently anchored? Does code trigger /tech/?
▶ No.835056>>835058
>>835052
>silently anchored
>>>/g/
The bumplimit is 400 posts. Make a new thread.
▶ No.835058
>>835056
> bumplimit is 400 posts
Ahh. We might as well keep this thread until full.
▶ No.835061>>835065 >>835081
Wtf this shit is too easy: https://play.rust-lang.org/?gist=0720b3a232a28b8e524ae589300745f7
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) = iter.next() {
match b {
b'>' => { garbage = false; }
b'!' => { iter.next(); }
b'<' if !garbage => { garbage = true; }
b'{' if !garbage => { group += 1; solution_part1 += group; }
b'}' if !garbage => { group -= 1; }
_ if garbage => { solution_part2 += 1; }
_ => {}
}
}
}
▶ No.835065
▶ No.835067
▶ No.835081
>>835061
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, '<' -> garbage := true
| false, '{' -> incr group; answer1 := !answer1 + !group
| false, '}' -> decr group
| true, _ -> incr answer2
| _, _ -> ()
done;
(!answer1, !answer2)
with the bytecode compiler it's nearly half the speed of my solution above; with ocamlopt it's marginally faster:
$ ./day9
mine 10000 iterations: 0.000058 s
rust 10000 iterations: 0.000057 s
$ ./day9
mine 10000 iterations: 0.000058 s
rust 10000 iterations: 0.000056 s
$ ./day9
mine 10000 iterations: 0.000063 s
rust 10000 iterations: 0.000056 s
$ ./day9.byte
mine 10000 iterations: 0.000251 s
rust 10000 iterations: 0.000491 s
the timing is the real timing / iterations ofc.
▶ No.835167>>835180
How many of you guys actually log into the site?
▶ No.835180
>>835167
you have to log into it to get the puzzles. IIRC I just used a github throwaway.
▶ No.835307
New thread: >>835306
New thread: >>835306
New thread: >>835306
New thread: >>835306