commit
a5b5bcfc3b
@ -0,0 +1 @@ |
|||||||
|
**/*.input |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,22 @@ |
|||||||
|
#!python3 |
||||||
|
import re |
||||||
|
|
||||||
|
digits = "one two three four five six seven eight nine".split(" ") |
||||||
|
|
||||||
|
nums_of_digits = dict((b, str(a+1)) for (a, b) in enumerate(digits)) |
||||||
|
or_of_digits = "|".join(digits) |
||||||
|
first_re = re.compile("\D*?(\d|" + or_of_digits + ").*") |
||||||
|
second_re = re.compile(".*(\d|" + or_of_digits + ")\D*?") |
||||||
|
|
||||||
|
with open("input01d", "r") as f: |
||||||
|
s = 0 |
||||||
|
for line in f.readlines(): |
||||||
|
first = first_re.match(line).group(1) |
||||||
|
second = second_re.match(line).group(1) |
||||||
|
if first in digits: |
||||||
|
first = nums_of_digits[first] |
||||||
|
if second in digits: |
||||||
|
second = nums_of_digits[second] |
||||||
|
s += int(first + second) |
||||||
|
print(s) |
||||||
|
|
@ -0,0 +1,53 @@ |
|||||||
|
#!python3 |
||||||
|
import re |
||||||
|
|
||||||
|
import argparse |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument("filename", help="the file from which to take the list of games") |
||||||
|
parser.add_argument("red_max", help="how many reds are available", type=int) |
||||||
|
parser.add_argument("green_max", help="how many greens are available", type=int) |
||||||
|
parser.add_argument("blue_max", help="how many blues are available", type=int) |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
line_re = re.compile("Game (\d+):(.*)") |
||||||
|
red_re = re.compile(".*?(\d+) red.*") |
||||||
|
green_re = re.compile(".*?(\d+) green.*") |
||||||
|
blue_re = re.compile(".*?(\d+) blue.*") |
||||||
|
|
||||||
|
def game_from_line(string): |
||||||
|
m = line_re.match(string) |
||||||
|
game_number = int(m.group(1)) |
||||||
|
game_strings = m.group(2).split(";") |
||||||
|
games = [] |
||||||
|
for g in game_strings: |
||||||
|
reds = red_re.match(g) |
||||||
|
reds = int(reds.group(1)) if reds else 0 |
||||||
|
|
||||||
|
greens = green_re.match(g) |
||||||
|
greens = int(greens.group(1)) if greens else 0 |
||||||
|
|
||||||
|
blues = blue_re.match(g) |
||||||
|
blues = int(blues.group(1)) if blues else 0 |
||||||
|
|
||||||
|
games.append((reds, greens, blues)) |
||||||
|
|
||||||
|
return (game_number, games) |
||||||
|
|
||||||
|
all_games = [] |
||||||
|
with open(args.filename, "r") as f: |
||||||
|
for l in f.readlines(): |
||||||
|
all_games.append(game_from_line(l)) |
||||||
|
|
||||||
|
for l in all_games: |
||||||
|
print(l) |
||||||
|
|
||||||
|
answer = 0 |
||||||
|
for l in all_games: |
||||||
|
answer += l[0] |
||||||
|
for (r, g, b) in l[1]: |
||||||
|
if r > args.red_max or g > args.green_max or b > args.blue_max: |
||||||
|
answer -= l[0] |
||||||
|
break |
||||||
|
|
||||||
|
|
||||||
|
print(answer) |
@ -0,0 +1,43 @@ |
|||||||
|
#!python3 |
||||||
|
import re |
||||||
|
|
||||||
|
import argparse |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument("filename", help="the file from which to take the list of games") |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
line_re = re.compile("Game (\d+):(.*)") |
||||||
|
red_re = re.compile(".*?(\d+) red.*") |
||||||
|
green_re = re.compile(".*?(\d+) green.*") |
||||||
|
blue_re = re.compile(".*?(\d+) blue.*") |
||||||
|
|
||||||
|
def game_from_line(string): |
||||||
|
m = line_re.match(string) |
||||||
|
game_number = int(m.group(1)) |
||||||
|
game_strings = m.group(2).split(";") |
||||||
|
games = [] |
||||||
|
for g in game_strings: |
||||||
|
reds = red_re.match(g) |
||||||
|
reds = int(reds.group(1)) if reds else 0 |
||||||
|
|
||||||
|
greens = green_re.match(g) |
||||||
|
greens = int(greens.group(1)) if greens else 0 |
||||||
|
|
||||||
|
blues = blue_re.match(g) |
||||||
|
blues = int(blues.group(1)) if blues else 0 |
||||||
|
|
||||||
|
games.append((reds, greens, blues)) |
||||||
|
|
||||||
|
return (game_number, games) |
||||||
|
|
||||||
|
all_games = [] |
||||||
|
with open(args.filename, "r") as f: |
||||||
|
for l in f.readlines(): |
||||||
|
all_games.append(game_from_line(l)) |
||||||
|
|
||||||
|
answer = 0 |
||||||
|
for l in all_games: |
||||||
|
r, g, b = map(max, zip(*l[1])) |
||||||
|
answer += r*g*b |
||||||
|
|
||||||
|
print(answer) |
@ -0,0 +1,138 @@ |
|||||||
|
#!python3 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import argparse |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument("filename", help="the file from which to take the list of games") |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
parts = [] |
||||||
|
notparts = [] |
||||||
|
gearsum = 0 |
||||||
|
|
||||||
|
|
||||||
|
def check_neighbors(nbrs): |
||||||
|
for n in nbrs: |
||||||
|
if n not in ".0123456789\n": |
||||||
|
return True |
||||||
|
|
||||||
|
def neighbors(x, y, ls): |
||||||
|
out = [] |
||||||
|
for dx in range(-1,2): |
||||||
|
for dy in range(-1,2): |
||||||
|
if dx == 0 and dy == 0: |
||||||
|
continue |
||||||
|
if y+dy < 0 or y+dy >= len(ls): |
||||||
|
continue |
||||||
|
if x+dx < 0 or x+dx >= len(ls[y+dy]): |
||||||
|
continue |
||||||
|
out.append(ls[y+dy][x+dx]) |
||||||
|
return out |
||||||
|
|
||||||
|
def numerical_neighbors(x, y, ls): |
||||||
|
out = set() |
||||||
|
for dx in range(-1, 2): |
||||||
|
for dy in range(-1, 2): |
||||||
|
if dx == 0 and dy == 0: |
||||||
|
continue |
||||||
|
if y+dy < 0 or y+dy >= len(ls): |
||||||
|
continue |
||||||
|
if x+dx < 0 or x+dx >= len(ls[y+dy]): |
||||||
|
continue |
||||||
|
|
||||||
|
|
||||||
|
if ls[y+dy][x+dx] in "0123456789": |
||||||
|
out |= {(x+dx,y+dy, ls[y+dy][x+dx])} |
||||||
|
|
||||||
|
return out |
||||||
|
|
||||||
|
def get_number(x,y, lines): |
||||||
|
"""assumes (x,y) is the coordinates of a digit in lines""" |
||||||
|
while x-1 >= 0 and lines[y][x-1] in "0123456789": |
||||||
|
x = x-1 |
||||||
|
start = (x,y) |
||||||
|
|
||||||
|
number = "" |
||||||
|
coords = set() |
||||||
|
while lines[y][x] in "0123456789": |
||||||
|
number += lines[y][x] |
||||||
|
coords |= {(x,y)} |
||||||
|
x += 1 |
||||||
|
if x >= len(lines[y]): break |
||||||
|
|
||||||
|
return (number, frozenset(coords)) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
with open(args.filename, "r") as file: |
||||||
|
lines = file.readlines() |
||||||
|
for y, l in enumerate(lines): |
||||||
|
number = "" |
||||||
|
nbrs = [] |
||||||
|
for x, c in enumerate(l): |
||||||
|
if c == "\n": print("HEYYYY") |
||||||
|
if c in "0123456789": |
||||||
|
number = number + c |
||||||
|
nbrs.extend(neighbors(x,y,lines)) |
||||||
|
if c not in "0123456789\n" and number != "": |
||||||
|
if check_neighbors(nbrs): |
||||||
|
#print("found a number:", number, "".join(nbrs), " and accepted it") |
||||||
|
parts.append(int(number)) |
||||||
|
else: |
||||||
|
#print("found a number:", number, "".join(nbrs), " and rejected it") |
||||||
|
notparts.append(int(number)) |
||||||
|
number = "" |
||||||
|
nbrs = [] |
||||||
|
if c not in "0123456789": |
||||||
|
continue |
||||||
|
if number != "": |
||||||
|
if check_neighbors(nbrs): |
||||||
|
print("found a number:", number, "".join(nbrs), " and accepted it") |
||||||
|
parts.append(int(number)) |
||||||
|
else: |
||||||
|
print("found a number:", number, "".join(nbrs), " and rejected it") |
||||||
|
notparts.append(int(number)) |
||||||
|
number = "" |
||||||
|
nbrs = [] |
||||||
|
|
||||||
|
|
||||||
|
gearsum = 0 |
||||||
|
for y, l in enumerate(lines): |
||||||
|
for x, c in enumerate(l): |
||||||
|
if c == "*": |
||||||
|
print("found a gear at ", x, " ", y) |
||||||
|
gear_nums = [] |
||||||
|
gear_coordsets = set() |
||||||
|
# we found a gear |
||||||
|
neighbors = numerical_neighbors(x,y,lines) |
||||||
|
print("the gear had neighbors ", neighbors) |
||||||
|
for xa, ya, neighboring_number in neighbors: |
||||||
|
number, coords = get_number(xa, ya, lines) |
||||||
|
print("found a neighbor ", number, " at coords ", coords) |
||||||
|
if coords in gear_coordsets: |
||||||
|
print("rejecting that neighbor because we already got it") |
||||||
|
# we've already got this number. mvoe alnog |
||||||
|
continue |
||||||
|
else: |
||||||
|
print("adding it to gear cordsets", gear_coordsets) |
||||||
|
gear_nums.append(number) |
||||||
|
gear_coordsets |= {coords} |
||||||
|
print("which corresponded to numbers", gear_nums) |
||||||
|
|
||||||
|
if len(gear_nums) == 2: |
||||||
|
gearsum += int(gear_nums[0])*int(gear_nums[1]) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print("accepted:") |
||||||
|
print(parts) |
||||||
|
print("rejected:") |
||||||
|
print(notparts) |
||||||
|
|
||||||
|
print("sum of parts are:", sum(parts)) |
||||||
|
print("sum of unique parts are: ", sum(set(parts))) |
||||||
|
print("gear sum is: ", gearsum) |
||||||
|
|
||||||
|
|
@ -0,0 +1,42 @@ |
|||||||
|
#!python3 |
||||||
|
|
||||||
|
import re |
||||||
|
import argparse |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument("filename", help="the file from which to take data") |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
points = 0 |
||||||
|
with open(args.filename, "r") as f: |
||||||
|
for l in f.readlines(): |
||||||
|
secondhalf = l.split(":")[1] |
||||||
|
winning = set(secondhalf.split("|")[0].split()) |
||||||
|
ours = set(secondhalf.split("|")[1].split()) |
||||||
|
print(winning & ours) |
||||||
|
points += 2 ** (len(winning & ours) - 1) if winning & ours else 0 |
||||||
|
|
||||||
|
print(points) |
||||||
|
|
||||||
|
|
||||||
|
line_re = re.compile("Card([ ]+\d+):(.*)\|(.*)") |
||||||
|
with open(args.filename, "r") as f: |
||||||
|
lines = f.readlines() |
||||||
|
games = [] |
||||||
|
for l in lines: |
||||||
|
games.append(1) |
||||||
|
print("starting ouot we have:") |
||||||
|
print(games) |
||||||
|
for l in lines: |
||||||
|
print(l) |
||||||
|
line = line_re.match(l) |
||||||
|
current_game_number = int(line.group(1)) |
||||||
|
winning = set(line.group(2).split()) |
||||||
|
ours = set(line.group(3).split()) |
||||||
|
wins = len(winning & ours) |
||||||
|
|
||||||
|
next_several = range(current_game_number, current_game_number+wins) |
||||||
|
for i in next_several: |
||||||
|
if i < len(games): |
||||||
|
games[i] += games[current_game_number-1] |
||||||
|
|
||||||
|
print(sum(games)) |
@ -0,0 +1,57 @@ |
|||||||
|
import re |
||||||
|
import argparse |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument("filename", help="the file from which to take data") |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
seeds = [] |
||||||
|
|
||||||
|
maps = [] # list of map lists |
||||||
|
with open(args.filename, "r") as f: |
||||||
|
seeds_re = re.compile("seeds: ((\d| )*)") |
||||||
|
new_map_re = re.compile("(.*?) map:") |
||||||
|
map_data_re = re.compile("\d+ \d+ \d+") |
||||||
|
|
||||||
|
current_map = [] |
||||||
|
for l in f.readlines(): |
||||||
|
if seeds_re.match(l): |
||||||
|
seeds = list(map(int, seeds_re.match(l).group(1).split())) |
||||||
|
|
||||||
|
if new_map_re.match(l): |
||||||
|
if current_map: |
||||||
|
maps.append(current_map) |
||||||
|
current_map = [] |
||||||
|
|
||||||
|
if map_data_re.match(l): |
||||||
|
current_map.append(list(map(int, map_data_re.match(l).group(0).split()))) |
||||||
|
|
||||||
|
if current_map: maps.append(current_map) |
||||||
|
|
||||||
|
print("seeds: ", seeds) |
||||||
|
print("maps are: ") |
||||||
|
for x in maps: print(x) |
||||||
|
|
||||||
|
def mapit(the_map, number): |
||||||
|
for destination_start, origin_start, length in the_map: |
||||||
|
offset = number - origin_start |
||||||
|
|
||||||
|
if offset < length and offset >= 0: |
||||||
|
return destination_start + offset |
||||||
|
|
||||||
|
return number |
||||||
|
|
||||||
|
def consecutive_maps(all_maps, number): |
||||||
|
output = [] |
||||||
|
output.append(number) |
||||||
|
for the_map in all_maps: |
||||||
|
number = mapit(the_map, number) |
||||||
|
output.append(number) |
||||||
|
|
||||||
|
return output |
||||||
|
|
||||||
|
consec_maps = [consecutive_maps(maps, s) for s in seeds] |
||||||
|
for s in consec_maps: print(s) |
||||||
|
|
||||||
|
print(list(sorted(consec_maps, key=lambda x: x[-1]))) |
@ -0,0 +1,66 @@ |
|||||||
|
import re |
||||||
|
import argparse |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument("filename", help="the file from which to take data") |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
seeds = [] |
||||||
|
|
||||||
|
maps = [] # list of map lists |
||||||
|
with open(args.filename, "r") as f: |
||||||
|
seeds_re = re.compile("seeds: ((\d| )*)") |
||||||
|
new_map_re = re.compile("(.*?) map:") |
||||||
|
map_data_re = re.compile("\d+ \d+ \d+") |
||||||
|
|
||||||
|
current_map = [] |
||||||
|
for l in f.readlines(): |
||||||
|
if seeds_re.match(l): |
||||||
|
seeds = list(map(int, seeds_re.match(l).group(1).split())) |
||||||
|
|
||||||
|
if new_map_re.match(l): |
||||||
|
if current_map: |
||||||
|
maps.append(current_map) |
||||||
|
current_map = [] |
||||||
|
|
||||||
|
if map_data_re.match(l): |
||||||
|
current_map.append(list(map(int, map_data_re.match(l).group(0).split()))) |
||||||
|
|
||||||
|
if current_map: maps.append(current_map) |
||||||
|
|
||||||
|
print("seeds: ", seeds) |
||||||
|
print("maps are: ") |
||||||
|
for x in maps: print(x) |
||||||
|
|
||||||
|
def mapit(the_map, number): |
||||||
|
for destination_start, origin_start, length in the_map: |
||||||
|
offset = number - origin_start |
||||||
|
|
||||||
|
if offset < length and offset >= 0: |
||||||
|
return destination_start + offset |
||||||
|
|
||||||
|
return number |
||||||
|
|
||||||
|
def consecutive_maps(all_maps, number): |
||||||
|
output = [] |
||||||
|
output.append(number) |
||||||
|
for the_map in all_maps: |
||||||
|
number = mapit(the_map, number) |
||||||
|
output.append(number) |
||||||
|
|
||||||
|
return output |
||||||
|
|
||||||
|
consec_maps = [consecutive_maps(maps, s) for s in seeds] |
||||||
|
for s in consec_maps: print(s) |
||||||
|
|
||||||
|
print("things sorted ", list(sorted(consec_maps, key=lambda x: x[-1]))) |
||||||
|
|
||||||
|
best = 9999999999999999 |
||||||
|
for i in range(0,len(seeds),2): |
||||||
|
for x in range(seeds[i], seeds[i]+seeds[i+1]): |
||||||
|
candidate = consecutive_maps(maps, x) |
||||||
|
if candidate[-1] < best: |
||||||
|
best = candidate[-1] |
||||||
|
|
||||||
|
print(best) |
@ -0,0 +1,73 @@ |
|||||||
|
use std::fs; |
||||||
|
use std::env; |
||||||
|
use std::iter::zip; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
println!("Hello world!"); |
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect(); |
||||||
|
if args.len() != 2 { |
||||||
|
println!("wrong number of arguments!"); |
||||||
|
std::process::exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
let file_path = &args[1]; |
||||||
|
|
||||||
|
// get time lineaswords and distance line as words
|
||||||
|
let binding = fs::read_to_string(file_path) |
||||||
|
.expect("Should have been able to read the file"); |
||||||
|
let mut contents = binding.lines(); |
||||||
|
|
||||||
|
let times = contents.next() |
||||||
|
.expect("should have a line of times"); |
||||||
|
let distances = contents.next() |
||||||
|
.expect("should have aline of distances"); |
||||||
|
|
||||||
|
let pairs = zip( |
||||||
|
times.split_whitespace(), |
||||||
|
distances.split_whitespace()).skip(1);
|
||||||
|
// skip the first (label)
|
||||||
|
|
||||||
|
let mut product = 1; |
||||||
|
for (time_s, distance_s) in pairs { |
||||||
|
let time: u128 = time_s.parse().unwrap(); |
||||||
|
let distance: u128 = distance_s.parse().unwrap(); |
||||||
|
println!("{} ms, {} meters", time, distance); |
||||||
|
|
||||||
|
let winning_strats = win(time, distance); |
||||||
|
println!("there are {} ways to win", winning_strats); |
||||||
|
|
||||||
|
product = product * winning_strats; |
||||||
|
} |
||||||
|
|
||||||
|
println!("product of winning strats is {}", product); |
||||||
|
|
||||||
|
let time_s = String::from( |
||||||
|
times.replace(" ","").rsplit(':').next() |
||||||
|
.expect("we should have a time") |
||||||
|
); |
||||||
|
let distance_s = String::from( |
||||||
|
distances.replace(" ","").rsplit(':').next() |
||||||
|
.expect("we should have a distance") |
||||||
|
); |
||||||
|
println!("the big race is {} milliseconds and {} meters",
|
||||||
|
time_s,
|
||||||
|
distance_s); |
||||||
|
|
||||||
|
let time: u128 = time_s.parse().unwrap(); |
||||||
|
let distance: u128 = distance_s.parse().unwrap(); |
||||||
|
|
||||||
|
println!("{} ms, {} meters", time, distance); |
||||||
|
println!("{} wins", win(time,distance)); |
||||||
|
} |
||||||
|
|
||||||
|
fn win(time: u128, distance: u128) -> u128 { |
||||||
|
let mut num_wins = 0; |
||||||
|
for delay in 0..time { |
||||||
|
if delay * (time - delay) > distance { |
||||||
|
num_wins = num_wins + 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return num_wins; |
||||||
|
} |
@ -0,0 +1,123 @@ |
|||||||
|
use std::iter::*; |
||||||
|
use std::cmp::*; |
||||||
|
use std::collections::HashMap; |
||||||
|
use std::fs; |
||||||
|
use std::env; |
||||||
|
|
||||||
|
|
||||||
|
type Hand = [usize;5]; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let card_value: HashMap<char, usize> = zip([ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J','Q', 'K', 'A'], 0..13).collect(); |
||||||
|
|
||||||
|
println!("Hello, AoC day 7!"); |
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect(); |
||||||
|
if args.len() != 2 { |
||||||
|
println!("wrong number of arguments!"); |
||||||
|
std::process::exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
let file_path = &args[1]; |
||||||
|
|
||||||
|
// get time lineaswords and distance line as words
|
||||||
|
let binding = fs::read_to_string(file_path) |
||||||
|
.expect("Should have been able to read the file"); |
||||||
|
let contents = binding.lines(); |
||||||
|
|
||||||
|
let mut hands: Vec<(Hand, u32)> = Vec::new(); |
||||||
|
|
||||||
|
for line in contents { |
||||||
|
if !line.is_empty() { |
||||||
|
hands.push(parse(line, &card_value)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
hands.sort_unstable_by(|(ha, _), (hb, _)| hand_compare(*ha, *hb)); |
||||||
|
|
||||||
|
let mut sum = 0; |
||||||
|
for (index, (_hand, bet)) in hands.iter().enumerate() { |
||||||
|
let score = ((index as u32) + 1) * bet; |
||||||
|
sum += score; |
||||||
|
} |
||||||
|
|
||||||
|
println!("total scores was: {}", sum); |
||||||
|
} |
||||||
|
|
||||||
|
fn parse(line: &str, dictionary: &HashMap<char, usize>) -> (Hand, u32) { |
||||||
|
let (hand, value) = line.split_once(" ").expect("expected a line to have the format 'AAAAA ###'"); |
||||||
|
let mut m: [usize;5] = [0;5]; |
||||||
|
|
||||||
|
for (i, character) in hand.chars().enumerate() { |
||||||
|
m[i] = *dictionary.get(&character).expect(&format!("expected a card in {}", line)); |
||||||
|
} |
||||||
|
|
||||||
|
let val:u32 = value.parse().unwrap(); |
||||||
|
println!("{:?} for {}", m, val); |
||||||
|
return (m, val); |
||||||
|
} |
||||||
|
|
||||||
|
fn rank(hand: Hand) -> u32 { |
||||||
|
let mut a = [0; 13]; |
||||||
|
for letter in hand { |
||||||
|
a[letter] += 1; |
||||||
|
} |
||||||
|
|
||||||
|
let mut fives = 0; |
||||||
|
let mut fours = 0; |
||||||
|
let mut threes = 0; |
||||||
|
let mut twos = 0; |
||||||
|
let mut _ones = 0; |
||||||
|
|
||||||
|
for number in a { |
||||||
|
match number { |
||||||
|
5 => fives += 1, |
||||||
|
4 => fours += 1, |
||||||
|
3 => threes += 1, |
||||||
|
2 => twos += 1, |
||||||
|
1 => _ones += 1, |
||||||
|
_ => () |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if fives > 0 { |
||||||
|
return 6; |
||||||
|
} |
||||||
|
if fours > 0 { |
||||||
|
return 5; |
||||||
|
} |
||||||
|
if threes == 1 && twos == 1 { |
||||||
|
return 4; |
||||||
|
} |
||||||
|
if threes == 1 { |
||||||
|
return 3; |
||||||
|
} |
||||||
|
if twos == 2 { |
||||||
|
return 2; |
||||||
|
} |
||||||
|
if twos == 1 { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
fn hand_compare(a: Hand, b: Hand) -> Ordering { |
||||||
|
let bs_a = rank(a); |
||||||
|
let bs_b = rank(b); |
||||||
|
|
||||||
|
if bs_a > bs_b { |
||||||
|
return Ordering::Greater; |
||||||
|
} else if bs_a < bs_b { |
||||||
|
return Ordering::Less; |
||||||
|
} |
||||||
|
|
||||||
|
if a > b { |
||||||
|
return Ordering::Greater; |
||||||
|
} else if a < b { |
||||||
|
return Ordering::Less; |
||||||
|
} |
||||||
|
|
||||||
|
return Ordering::Equal; |
||||||
|
} |
@ -0,0 +1,149 @@ |
|||||||
|
use std::iter::*; |
||||||
|
use std::cmp::*; |
||||||
|
use std::collections::HashMap; |
||||||
|
use std::fs; |
||||||
|
use std::env; |
||||||
|
|
||||||
|
|
||||||
|
type Hand = [usize;5]; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let card_value: HashMap<char, usize> = zip(['J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A'], 0..13).collect(); |
||||||
|
|
||||||
|
println!("Hello, AoC day 7!"); |
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect(); |
||||||
|
if args.len() != 2 { |
||||||
|
println!("wrong number of arguments!"); |
||||||
|
std::process::exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
let file_path = &args[1]; |
||||||
|
|
||||||
|
let binding = fs::read_to_string(file_path) |
||||||
|
.expect("Should have been able to read the file"); |
||||||
|
let contents = binding.lines(); |
||||||
|
|
||||||
|
let mut hands: Vec<(Hand, u32)> = Vec::new(); |
||||||
|
|
||||||
|
for line in contents { |
||||||
|
if !line.is_empty() { |
||||||
|
hands.push(parse(line, &card_value)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
hands.sort_by(|(ha, _), (hb, _)| hand_compare(*ha, *hb)); |
||||||
|
|
||||||
|
println!("and now, the sorted:"); |
||||||
|
for (hand, value) in hands.iter() { |
||||||
|
let ran = match rank(*hand) { |
||||||
|
6 => "five of a kind", |
||||||
|
5 => "four of a kind", |
||||||
|
4 => "full house", |
||||||
|
3 => "three of a kind", |
||||||
|
2 => "two pair", |
||||||
|
1 => "one pair", |
||||||
|
0 => "card high", |
||||||
|
_ => "mystery to us all" |
||||||
|
}; |
||||||
|
println!("{:?}, which is a {}, for {}", hand, ran, value); |
||||||
|
} |
||||||
|
|
||||||
|
let mut sum = 0; |
||||||
|
for (index, (_hand, bet)) in hands.iter().enumerate() { |
||||||
|
let score = ((index as u32) + 1) * bet; |
||||||
|
sum += score; |
||||||
|
} |
||||||
|
|
||||||
|
println!("total scores was: {}", sum); |
||||||
|
} |
||||||
|
|
||||||
|
fn parse(line: &str, dictionary: &HashMap<char, usize>) -> (Hand, u32) { |
||||||
|
let (hand, value) = line.split_once(" ").expect("expected a line to have the format 'AAAAA ###'"); |
||||||
|
let mut m: [usize;5] = [0;5]; |
||||||
|
|
||||||
|
for (i, character) in hand.chars().enumerate() { |
||||||
|
m[i] = *dictionary.get(&character).expect(&format!("expected a card in {}", line)); |
||||||
|
} |
||||||
|
|
||||||
|
return (m, value.parse().unwrap());
|
||||||
|
} |
||||||
|
|
||||||
|
fn rank(hand: Hand) -> u32 { |
||||||
|
let mut a = [0; 13]; |
||||||
|
for letter in hand { |
||||||
|
a[letter] += 1; |
||||||
|
} |
||||||
|
|
||||||
|
let mut fives = 0; |
||||||
|
let mut fours = 0; |
||||||
|
let mut threes = 0; |
||||||
|
let mut twos = 0; |
||||||
|
let mut _ones = 0; |
||||||
|
|
||||||
|
for number in &a[1..] { |
||||||
|
|
||||||
|
match number { |
||||||
|
5 => fives += 1, |
||||||
|
4 => fours += 1, |
||||||
|
3 => threes += 1, |
||||||
|
2 => twos += 1, |
||||||
|
1 => _ones += 1, |
||||||
|
_ => () |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (fives > 0) ||
|
||||||
|
((fours == 1) && (a[0] == 1)) || |
||||||
|
((threes == 1) && (a[0] == 2)) || |
||||||
|
((twos == 1) && (a[0] == 3)) || |
||||||
|
(a[0] == 4) ||
|
||||||
|
(a[0] == 5) { |
||||||
|
return 6; |
||||||
|
} |
||||||
|
if (fours > 0) || |
||||||
|
((threes == 1) && (a[0] == 1)) || |
||||||
|
((twos == 1) && (a[0] == 2)) || |
||||||
|
(a[0] == 3) || |
||||||
|
(a[0] == 4) { |
||||||
|
return 5; |
||||||
|
} |
||||||
|
if (threes == 1 && twos == 1) || |
||||||
|
((twos == 2) && (a[0] == 1)) { |
||||||
|
return 4; |
||||||
|
} |
||||||
|
if (threes == 1) || |
||||||
|
((twos == 1) && (a[0] == 1)) || |
||||||
|
(a[0] == 2) { |
||||||
|
return 3; |
||||||
|
} |
||||||
|
if twos == 2 { |
||||||
|
return 2; |
||||||
|
} |
||||||
|
if (twos == 1) || |
||||||
|
(a[0] == 1) { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
fn hand_compare(a: Hand, b: Hand) -> Ordering { |
||||||
|
let bs_a = rank(a); |
||||||
|
let bs_b = rank(b); |
||||||
|
|
||||||
|
if bs_a > bs_b { |
||||||
|
return Ordering::Greater; |
||||||
|
} else if bs_a < bs_b { |
||||||
|
return Ordering::Less; |
||||||
|
} |
||||||
|
|
||||||
|
if a > b { |
||||||
|
return Ordering::Greater; |
||||||
|
} else if a < b { |
||||||
|
return Ordering::Less; |
||||||
|
} |
||||||
|
|
||||||
|
return Ordering::Equal; |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
/target |
@ -0,0 +1,54 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
version = 3 |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "aho-corasick" |
||||||
|
version = "1.1.2" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" |
||||||
|
dependencies = [ |
||||||
|
"memchr", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "day08" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"regex", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "memchr" |
||||||
|
version = "2.6.4" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "regex" |
||||||
|
version = "1.10.2" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" |
||||||
|
dependencies = [ |
||||||
|
"aho-corasick", |
||||||
|
"memchr", |
||||||
|
"regex-automata", |
||||||
|
"regex-syntax", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "regex-automata" |
||||||
|
version = "0.4.3" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" |
||||||
|
dependencies = [ |
||||||
|
"aho-corasick", |
||||||
|
"memchr", |
||||||
|
"regex-syntax", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "regex-syntax" |
||||||
|
version = "0.8.2" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" |
@ -0,0 +1,9 @@ |
|||||||
|
[package] |
||||||
|
name = "day08" |
||||||
|
version = "0.1.0" |
||||||
|
edition = "2021" |
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||||
|
|
||||||
|
[dependencies] |
||||||
|
regex = "1.10.2" |
@ -0,0 +1,78 @@ |
|||||||
|
use std::fs; |
||||||
|
use std::env; |
||||||
|
use regex::Regex; |
||||||
|
use std::collections::HashMap; |
||||||
|
|
||||||
|
//type Choice = (&str, &str);
|
||||||
|
|
||||||
|
fn main() { |
||||||
|
println!("Hello AoC day 8!"); |
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect(); |
||||||
|
if args.len() != 2 { |
||||||
|
println!("wrong number of arguments!"); |
||||||
|
std::process::exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
let file_path = &args[1]; |
||||||
|
|
||||||
|
// get time lineaswords and distance line as words
|
||||||
|
let binding = fs::read_to_string(file_path) |
||||||
|
.expect("Should have been able to read the file"); |
||||||
|
let mut contents = binding.lines(); |
||||||
|
|
||||||
|
let directions = contents.next().expect("There has to be a first line...").to_string(); |
||||||
|
let re = Regex::new(r"(\w\w\w) = \((\w\w\w), (\w\w\w)\)").unwrap(); |
||||||
|
|
||||||
|
let mut our_map = HashMap::new(); |
||||||
|
let mut feet = Vec::new(); |
||||||
|
|
||||||
|
for line in contents { |
||||||
|
let Some(capture) = re.captures(line) else { continue }; |
||||||
|
match re.captures(line) { |
||||||
|
Some(capture) => { |
||||||
|
let this = capture[1].to_string(); |
||||||
|
if this.chars().nth(2) == Some('A') { |
||||||
|
feet.push(this.to_string()); |
||||||
|
} |
||||||
|
let those = (capture[2].to_string(), capture[3].to_string()); |
||||||
|
our_map.insert(this, those); |
||||||
|
() |
||||||
|
}, |
||||||
|
None => () |
||||||
|
} |
||||||
|
} |
||||||
|
println!("our directions list is {}", directions); |
||||||
|
//println!("{:?}", our_map);
|
||||||
|
|
||||||
|
println!("starting at {feet:?}"); |
||||||
|
let mut z_lengths = Vec::new(); |
||||||
|
//let mut z_cycles = Vec::new();
|
||||||
|
let mut count = 0; |
||||||
|
|
||||||
|
|
||||||
|
while !finished(&feet) { |
||||||
|
let mut iter = directions.chars(); |
||||||
|
for i in 0..feet.len() { |
||||||
|
let (left, right) = our_map.get(&feet[i]).expect("we should stay on the map."); |
||||||
|
match iter.next() { |
||||||
|
Some('L') => {feet[i] = left.to_string();}, |
||||||
|
Some('R') => {feet[i] = right.to_string();}, |
||||||
|
_ => {iter = directions.chars();} |
||||||
|
} |
||||||
|
} |
||||||
|
count += 1; |
||||||
|
|
||||||
|
z_lengths.push(count); |
||||||
|
} |
||||||
|
println!("we walked {count} steps!"); |
||||||
|
//println!("the cycle lengths were {z_cycles:?}")
|
||||||
|
} |
||||||
|
|
||||||
|
fn finished(spot: &Vec<String> ) -> bool { |
||||||
|
let mut output = true; |
||||||
|
for foot in spot { |
||||||
|
output = output && (foot.chars().nth(2) == Some('Z')) |
||||||
|
} |
||||||
|
return output; |
||||||
|
} |
@ -0,0 +1,86 @@ |
|||||||
|
use std::fs; |
||||||
|
use std::env; |
||||||
|
use regex::Regex; |
||||||
|
use std::collections::HashMap; |
||||||
|
|
||||||
|
//type Choice = (&str, &str);
|
||||||
|
|
||||||
|
fn main() { |
||||||
|
println!("Hello AoC day 8!"); |
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect(); |
||||||
|
if args.len() != 2 { |
||||||
|
println!("wrong number of arguments!"); |
||||||
|
std::process::exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
let file_path = &args[1]; |
||||||
|
|
||||||
|
// get time lineaswords and distance line as words
|
||||||
|
let binding = fs::read_to_string(file_path) |
||||||
|
.expect("Should have been able to read the file"); |
||||||
|
let mut contents = binding.lines(); |
||||||
|
|
||||||
|
let directions = contents.next().expect("There has to be a first line...").to_string(); |
||||||
|
let re = Regex::new(r"(\w\w\w) = \((\w\w\w), (\w\w\w)\)").unwrap(); |
||||||
|
|
||||||
|
let mut our_map = HashMap::new(); |
||||||
|
let mut feet = Vec::new(); |
||||||
|
|
||||||
|
for line in contents { |
||||||
|
let Some(capture) = re.captures(line) else { continue }; |
||||||
|
match re.captures(line) { |
||||||
|
Some(capture) => { |
||||||
|
let this = capture[1].to_string(); |
||||||
|
if this.chars().nth(2) == Some('A') { |
||||||
|
feet.push(this.to_string()); |
||||||
|
} |
||||||
|
let those = (capture[2].to_string(), capture[3].to_string()); |
||||||
|
our_map.insert(this, those); |
||||||
|
() |
||||||
|
}, |
||||||
|
None => () |
||||||
|
} |
||||||
|
} |
||||||
|
println!("our directions list is {}", directions); |
||||||
|
//println!("{:?}", our_map);
|
||||||
|
|
||||||
|
println!("starting at {feet:?}"); |
||||||
|
let mut z_lengths = Vec::new(); |
||||||
|
//let mut z_cycles = Vec::new();
|
||||||
|
|
||||||
|
for foot in feet { |
||||||
|
let mut here = &foot; |
||||||
|
let mut iter = directions.chars(); |
||||||
|
let mut count = 0; |
||||||
|
|
||||||
|
while here.chars().nth(2) != Some('Z') { |
||||||
|
let (left, right) = our_map.get(here).expect("we should stay on the map."); |
||||||
|
match iter.next() { |
||||||
|
Some('L') => { |
||||||
|
here = left; |
||||||
|
count += 1; |
||||||
|
}, |
||||||
|
Some('R') => { |
||||||
|
here = right; |
||||||
|
count += 1; |
||||||
|
}, |
||||||
|
_ => { |
||||||
|
iter = directions.chars(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
z_lengths.push(count); |
||||||
|
} |
||||||
|
println!("we walked {z_lengths:?} steps!"); |
||||||
|
//println!("the cycle lengths were {z_cycles:?}")
|
||||||
|
} |
||||||
|
|
||||||
|
fn finished(spot: &Vec<String> ) -> bool { |
||||||
|
let mut output = true; |
||||||
|
for foot in spot { |
||||||
|
output = output && (foot.chars().nth(2) == Some('Z')) |
||||||
|
} |
||||||
|
return output; |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
/target |
@ -0,0 +1,7 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
version = 3 |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "day09" |
||||||
|
version = "0.1.0" |
@ -0,0 +1,8 @@ |
|||||||
|
[package] |
||||||
|
name = "day09" |
||||||
|
version = "0.1.0" |
||||||
|
edition = "2021" |
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||||
|
|
||||||
|
[dependencies] |
@ -0,0 +1,77 @@ |
|||||||
|
use std::iter::*; |
||||||
|
use std::fs; |
||||||
|
use std::env; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
println!("Hello, AoC day 9!"); |
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect(); |
||||||
|
if args.len() != 2 { |
||||||
|
println!("wrong number of arguments!"); |
||||||
|
std::process::exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
let file_path = &args[1]; |
||||||
|
|
||||||
|
// get time lineaswords and distance line as words
|
||||||
|
let binding = fs::read_to_string(file_path) |
||||||
|
.expect("Should have been able to read the file"); |
||||||
|
let contents = binding.lines(); |
||||||
|
|
||||||
|
let mut sum_of_nexts = 0; |
||||||
|
let mut sum_of_prevs = 0; |
||||||
|
|
||||||
|
for line in contents { |
||||||
|
let nums: Vec<i64> = line.split_whitespace().map(|x| x.parse::<i64>().expect("ran into an unparseable number")).collect(); |
||||||
|
println!("{nums:?}"); |
||||||
|
|
||||||
|
let mut stack: Vec<Vec<i64>> = Vec::new(); |
||||||
|
stack.push(nums); |
||||||
|
|
||||||
|
while !all_zero(&(stack.last().expect("we should have at least one set of values. in the list"))) { |
||||||
|
let mut diffs = Vec::new(); |
||||||
|
let object = stack.pop().expect("our stack of values for differencing should have at least one list in it"); |
||||||
|
|
||||||
|
for i in 0..(object.len() - 1) { |
||||||
|
diffs.push(object[i+1] - object[i]); |
||||||
|
} |
||||||
|
println!("{diffs:?}"); |
||||||
|
|
||||||
|
stack.push(object); |
||||||
|
stack.push(diffs); |
||||||
|
} |
||||||
|
|
||||||
|
stack.reverse(); |
||||||
|
|
||||||
|
let mut difference = 0; |
||||||
|
|
||||||
|
for s in &stack { |
||||||
|
let start = s.last().expect("we shoulld always have values in our stack of difference lists"); |
||||||
|
difference = start + difference; |
||||||
|
} |
||||||
|
|
||||||
|
println!("the next value should be {difference}"); |
||||||
|
sum_of_nexts += difference; |
||||||
|
|
||||||
|
|
||||||
|
difference = 0; |
||||||
|
|
||||||
|
for s in &stack { |
||||||
|
let first = s.first().expect("we shoulld always have values in our stack of difference lists"); |
||||||
|
difference = first - difference; |
||||||
|
} |
||||||
|
println!("the previous value should be {difference}"); |
||||||
|
sum_of_prevs += difference; |
||||||
|
} |
||||||
|
|
||||||
|
println!("the sum of next values is {sum_of_nexts}"); |
||||||
|
println!("the sum of previous values is {sum_of_prevs}"); |
||||||
|
} |
||||||
|
|
||||||
|
fn all_zero(slice: &[i64]) -> bool { |
||||||
|
for s in slice { |
||||||
|
if *s != 0 { return false; } |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
Loading…
Reference in new issue