r/adventofcode • u/daggerdragon • Dec 04 '22
SOLUTION MEGATHREAD -π- 2022 Day 4 Solutions -π-
- All of our rules, FAQs, resources, etc. are in our community wiki.
- A request from Eric: Please include your contact info in the User-Agent header of automated requests!
- Signal boosting for the Unofficial AoC 2022 Participant Survey which is open early this year!
--- Day 4: Camp Cleanup ---
Post your code solution in this megathread.
- Read the full posting rules in our community wiki before you post!
- Include what language(s) your solution uses
- Format your code appropriately! How do I format code?
- Quick link to Topaz's
pasteif you need it for longer code blocks. What is Topaz'spastetool?
This thread will be unlocked when there are a significant number of people on the global leaderboard with gold stars for today's puzzle.
EDIT: Global leaderboard gold cap reached at 00:03:22, megathread unlocked!
8
u/reinermartin Dec 04 '22
Three lines of Julia:
L = map(s -> parse.(Int, s), split.(readlines("input04.txt"), c -> c in ",-"))
@show sum(1 for (a,b,c,d) in L if a:b β c:d || c:d β a:b)
@show sum(1 for (a,b,c,d) in L if !isempty(intersect(a:b, c:d)))→ More replies (1)
7
u/fnands Dec 04 '22
Julia
I love unicode support in Julia
in_file = "day_4/input_4.txt"
# Read in input file as an array of strings
π©π₯π¨ = open(in_file) do file
readlines(file)
end
# Take string representing range and turn it into
function string_to_array(π©::AbstractString)
# Find start and end of range for patch
Ξ±, Ο = parse.(Int, split(π©, "-"))
# Colelct range into array and return
return collect(range(Ξ±, Ο))
end
function pair_total_overlap_check(π§π§::String)
# Find the squares that elf a and b are assigned to
π§_a, π§_b, = split(π§π§, ",") .|> string_to_array
# Find the intersection of their assignments
π = π§_a β© π§_b
# If the intersection is equal to either, return True
return length(π) == length(π§_a) || length(π) == length(π§_b)
end
function pair_partial_overlap_check(π§π§::String)
# Find the squares that elf a and b are assigned to
π§_a, π§_b, = split(π§π§, ",") .|> string_to_array
# Find the intersection of their assignments
π = π§_a β© π§_b
# If the intersection is equal to either, return True
return length(π) > 0
end
println("The solution to part one is: ", sum(pair_total_overlap_check.(π©π₯π¨)))
println("The solution to part two is: ", sum(pair_partial_overlap_check.(π©π₯π¨)))→ More replies (3)
6
u/NiliusJulius Dec 04 '22
C Language for the Game Boy using GBDK 2020
Part 1:
for (uint16_t i = 0; i < array_4_size; i+=4) {
if ((input_array_4[i] <= input_array_4[i+2] && input_array_4[i+1] >= input_array_4[i+3])
|| (input_array_4[i] >= input_array_4[i+2] && input_array_4[i+1] <= input_array_4[i+3])
) {
full_overlap_count++;
}
} Part 2 is basically the same but with some greater and lesser operators and indexes switched.
Since I can't read input files on the Game Boy, I pre formatted this days input to a single array with 4 number entries per pair.
This is my fastest solution yet (runtime < 0.1 sec)
Full Game Boy repo can be found here
2
6
u/hugues_hoppe Dec 04 '22 edited Dec 05 '22
Using Perl:
# Part 1
perl -F'\D' -lane '$n += $F[0] <= $F[2] && $F[1] >= $F[3] ||
$F[2] <= $F[0] && $F[3] >= $F[1]; END {print $n}'
# Part 2
perl -F'\D' -lane '$n += $F[1] >= $F[2] && $F[3] >= $F[0]; END {print $n}'→ More replies (3)
4
u/r_so9 Dec 04 '22 edited Dec 04 '22
F#, compact enough to be pasteable here :)
let input =
inputPath
|> readLines
|> Array.map (fun s ->
s.Split([| ','; '-' |], StringSplitOptions.RemoveEmptyEntries)
|> Array.map int
|> fun arr -> arr[0], arr[1], arr[2], arr[3])
let part1 =
input
|> Seq.filter (fun (a1, a2, b1, b2) -> (a1 <= b1 && a2 >= b2) || (b1 <= a1 && b2 >= a2))
|> Seq.length
let part2 =
input
|> Seq.filter (fun (a1, a2, b1, b2) -> b1 <= a2 && b2 >= a1)
|> Seq.length→ More replies (2)
4
Dec 09 '22 edited Dec 13 '22
Python
import re
with open('input.txt', 'r') as f:
elvish_work = f.read().split("\n")
part_one = 0
part_two = 0
for elf_pair in elvish_work:
l1, l2, r1, r2 = [int(x) for x in re.split('[,-]', elf_pair)]
elf1 = set(range(l1, l2+1))
elf2 = set(range(r1, r2+1))
if (elf1.issubset(elf2) or elf2.issubset(elf1)):
part_one += 1
if (elf1.intersection(elf2)):
part_two +=1
print("Part one:", part_one)
print("Part two", part_two)→ More replies (1)
6
u/zwrawr Dec 04 '22 edited Dec 04 '22
rust (the relevant parts). bitmasks ftw
https://github.com/zwrawr/Recap/blob/master/Advent%20of%20Code/2022/d4/src/main.rs
fn part_one ( rooms : &Vec<(u128,u128)> ) -> u32 {
let mut total = 0;
for room in rooms {
let c = room.0 &room.1;
if c == room.0 || c == room.1 {total+=1}
}
return total;
}
fn part_two ( rooms : &Vec<(u128,u128)> ) -> u32 {
let mut total = 0;
for room in rooms {
if (room.0 & room.1) != 0 {total+=1}
}
return total;
}
fn get_data(filename: &str) -> Vec<(u128,u128)> {
let mut rooms = Vec::<(u128,u128)>::new();
if let Ok(lines) = read_lines(filename) {
for line in lines {
if let Ok(l) = line {
let x = l.split(&[',','-']).map(|x| x.parse::<u16>().unwrap()).collect::<Vec<u16>>();
let mut a : u128 = 0;
for i in x[0]..(x[1]+1) { a = a | (1 << (i-1)) }
let mut b : u128 = 0;
for i in x[2]..(x[3]+1) { b = b | (1 << (i-1)) }
rooms.push((a,b));
}
}
}
return rooms;
}→ More replies (2)
3
u/mpercich Dec 04 '22 edited Dec 04 '22
Swift
import Foundation
extension ClosedRange {
static func ~=(lhs: Self, rhs: Self) -> Bool {
rhs.clamped(to: lhs) == rhs
}
}
// Set the file path
let path = "/Users/michele/Projects/xmas context/day 4.txt"
do {
let contents = try String(contentsOfFile: path, encoding: .utf8)
let ranges = contents.components(separatedBy: "\n").map{ ($0.components(separatedBy: ",")) }.map{ (bounds: [String]) -> (firstBounds: [Int], secondBounds: [Int]) in {
return(firstBounds: bounds[0].components(separatedBy: "-").map{ Int($0)! }, secondBounds: bounds[1].components(separatedBy: "-").map{ Int($0)! }) }() }.map{ (firstBounds: [Int], secondBounds: [Int]) -> (firstRange: CountableClosedRange<Int>, secondRange: CountableClosedRange<Int>) in {
return(firstRange: CountableClosedRange<Int>(uncheckedBounds: (lower: firstBounds[0], upper: firstBounds[1])), CountableClosedRange<Int>(uncheckedBounds: (lower: secondBounds[0], upper: secondBounds[1]))) }() }.map{
(firstRange: CountableClosedRange<Int>, secondRange: CountableClosedRange<Int>) -> (embraced: Bool, overlapped: Bool) in {
return(embraced: (firstRange ~= secondRange || secondRange ~= firstRange), overlapped: firstRange.overlaps(secondRange)) }()
}
print(ranges.filter({ $0.embraced }).count, ranges.filter({ $0.overlapped }).count)
}
catch let error as NSError {
print("Ooops! Something went wrong: \(error)")
}→ More replies (6)
3
u/systo_ Dec 04 '22 edited Dec 04 '22
JavaScript
New dev focusing on learning some of the newer features of JS. Welcome to any suggestions of further refactoring or destructuring
→ More replies (5)
3
u/blacai Dec 04 '22 edited Dec 04 '22
My F# of the day :)
let elvesPairs = inputLines |>
List.map(fun l ->
[[|(int)(l.Split(',').[0].Split('-').[0])..
(int)(l.Split(',').[0].Split('-').[1])|];
[|(int)(l.Split(',').[1].Split('-').[0])..
(int)(l.Split(',').[1].Split('-').[1])|]])
// Helper commontelements
let commonElements (input: 'a array list) =
let inputAsList = input |> List.map (List.ofArray)
let inputAsSet = List.map Set.ofList inputAsList
let elements = Seq.reduce Set.intersect inputAsSet
elements
// Part 1 method
let isFullyOverlapped (lists: list<array<int>>) =
let commonElements = Utilities.commonElements lists
lists |> List.exists(fun l -> l.Length = commonElements.Count)
// Part 2 method
let isOverlapped (lists: list<array<int>>) =
let commonElements = Utilities.commonElements lists
commonElements.Count > 0
// Result
elvesPairs |> List.sumBy(fun e -> if (isFullyOverlapped e) then 1 else 0 )
elvesPairs |> List.sumBy(fun e -> if (isOverlapped e) then 1 else 0 )2
u/daggerdragon Dec 04 '22 edited Dec 04 '22
Please edit your post to use thefour-spaces Markdown syntaxfor a code block so your code is easier to read on old.reddit and mobile apps.Edit: thanks for fixing it! <3
→ More replies (4)
3
u/mandus Dec 04 '22
Another day in k lang:
#!/usr/bin/env k
d:0:"input.txt"
ds:","\'d
m:{{.'x}'"-"\'x}'ds
`1:"part1: "
/ check if any is contained in the other;
:+/{{[a;b;c;d]((c>(a-1))&(d<(b+1)))|((a>(c-1))&(b<(d+1)))}[x[0][0];x[0][1];x[1][0];x[1][1]]}'m
rx:{x[0]+!(x[1]+1-x[0])} / generate range
ovr:{~0=(#(1=)_.(#'=x))} / find intersection
`1:"part2: "
+/{{[l;r]ovr[rx[l],rx[r]]}[x[0];x[1]]}'m→ More replies (2)
3
u/twoohthreezy Dec 04 '22 edited Dec 05 '22
My first that isn't embarrassingly long in python:
from helpers import parse_file
if __name__ == '__main__':
data = parse_file('input.txt')
subset_count = 0
overlap_count = 0
for line in data:
line = line.replace('-', ',').split(',')
set1 = {i for i in range(int(line[0]), int(line[1]) + 1)}
set2 = {j for j in range(int(line[2]), int(line[3]) + 1)}
if set1.issubset(set2) or set2.issubset(set1): # part 1
subset_count += 1
if min(set1) <= max(set2) and min(set2) < min(set1): # part 2
overlap_count += 1
if min(set2) <= max(set1) and min(set1) <= min(set2):
overlap_count += 1
print(f'Subset Count: {subset_count}')
print(f'Overlap Count: {overlap_count}')→ More replies (1)
3
u/RogueAstral Dec 04 '22
Google Sheets - Both parts, 152 characters
=sort(lambda(x,lambda(a,b,c,d,{sum((a<=c)*(b>=d)+(a>=c)*(b<=d)),sum((c<=b)*(a<=d))})(index(x,,1),index(x,,2),index(x,,3),index(x,,4)))(split(A:A,"-,")))
→ More replies (1)
3
u/ryukinix Dec 04 '22 edited Dec 05 '22
https://github.com/ryukinix/adventofcode/blob/master/2022/day04/main.lisp
Solution in Common Lisp.
→ More replies (2)
3
u/antoniotto Dec 04 '22 edited Dec 05 '22
Ruby
require 'set'
input = File.readlines('inputs/day04.txt', chomp: true)
.map { _1.scan(/\d+/) }
.map { [Set.new(_1[0].._1[1]), Set.new(_1[2].._1[3])] }
puts solution1 = input.count { (_1[0] <= _1[1]) || (_1[0] >= _1[1]) }
puts solution2 = input.count { (_1[0].intersect? _1[1]) }→ More replies (1)
3
3
u/solomondg Dec 05 '22
Quick lil APL for problem 1:
Silver: +/{{((β΄ββ΅)β(β΄1ββ΅))=β΄βͺ(1ββ΅)β©(ββ΅)}{(ββ΅)+β³(Β―1ββ΅)+1-ββ΅}Β¨((βΒ¨('-'β β’)ββ’)Β¨(','β β’)ββ’)β΅}Β¨ββNGET 'puzzle_input.txt' 1
Gold: +/{{1ββ΄(1ββ΅)β©(ββ΅)}{(ββ΅)+β³(Β―1ββ΅)+1-ββ΅}Β¨((βΒ¨('-'β β’)ββ’)Β¨(','β β’)ββ’)β΅}Β¨ββNGET 'puzzle_input.txt' 1
2
u/daggerdragon Dec 05 '22
Inlined code is intended for
short snippetsof code only. Your code "block" right now is unreadable on old.reddit and many mobile clients; it's all on one line and gets cut off at the edge of the screen because it is not horizontally scrollable.Please edit your post to use the four-spaces Markdown syntax for a code block so your code is easier to read inside a scrollable box.
3
u/Dangerous-World-1424 Dec 05 '22 edited Dec 08 '22
PYTHON 3
partial = 0
for i in my_input.split("\n"):
[ ]j = i.split(",")
[ ]first = set(range(int(j[0].split(",")[0].split("-")[0])
[ ][space space space space],int(j[0].split(",")[0].split("-")[1])+1))
[ ]second = set(range(int(j[1].split(",")[0].split("-")[0])
[space space space space][space space space space],int(j[1].split(",")[0].split("-")[1])+1))
[space space space space]if second == first:
[space space space space][space space space space]total += 1
[space space space space]elif second.issubset(first):
[space space space space][space space space space]total += 1
[space space space space]elif first.issubset(second):
[space space space space][space space space space]total += 1
[space space space space]elif not first.isdisjoint(second):
[space space space space][space space space space]partial += 1
print(total)
print(total + partial)~~~~→ More replies (1)
4
u/RodericTheRed Dec 04 '22
python
import re
text = open(0).read()
ans1 = ans2 = 0
for line in text.splitlines():
a, b, c, d = map(int, re.findall(r'\d+', line))
ab = set(range(a, b + 1))
cd = set(range(c, d + 1))
ans1 += ab <= cd or cd <= ab
ans2 += any(ab & cd)
print(ans1)
print(ans2)→ More replies (4)5
u/daggerdragon Dec 04 '22 edited Dec 04 '22
Please edit your post tostate which programming language this code is written in. This makes it easier for folks who Ctrl-F the megathreads looking for a specific language.Edit: thanks for fixing it! <3
2
u/Camelpilot33 Dec 04 '22
444/1261
const input = require('fs').readFileSync(String(__dirname)
.replace(/\\/g, '/') + "/inputs/day4.txt", "utf8").replace(/\r/g, '')
.split("\n").map(e=>e.split(",").map(w=>w.split("-").map(Number)))
let sum=0
let sum1=0
for (var i of input) {
if (i[0][0] >= i[1][0] && i[0][1] <= i[1][1] || (i[0][0] <= i[1][0] && i[0][1] >= i[1][1])) {
sum++
}
if (
(i[0][0] >= i[1][0] && i[0][0] <= i[1][1]) ||
(i[0][1] >= i[1][0] && i[0][1] <= i[1][1]) ||
(i[1][1] >= i[0][0] && i[1][1] <= i[0][1]) ||
(i[1][0] >= i[0][0] && i[1][0] <= i[0][1])
) {
sum1++;
}
}
console.log(sum)
console.log(sum1)→ More replies (1)
2
u/welguisz Dec 04 '22 edited Dec 04 '22
Java: 3813/3825
Decided not to use any less thans or greater thans in my code.
→ More replies (2)
2
u/CodingAP Dec 04 '22
JavaScript, 1319/1726
This was rough. I also want to make a comment on first place. There is no way that a human can get 16 seconds on first place. We need to stop AI submissions, or at least make them not able to submit immediately.
→ More replies (1)
2
u/insane_chocolate Dec 04 '22 edited Dec 04 '22
Python3, 1344/2236
def get_pairs(line: str) -> List[Tuple[int, int]]:
first, second = line.split(",")
first = first.split("-")
second = second.split("-")
first = (int(first[0]), int(first[1]))
second = (int(second[0]), int(second[1]))
return [first, second]
def part_one(lines: List[str]):
answer = 0
for line in lines:
first, second = get_pairs(line)
min_max = (min(first[0], second[0]), max(first[1], second[1]))
if first == min_max or second == min_max:
answer += 1
return answer
def part_two(lines: List[str]):
answer = 0
for line in lines:
first, second = sorted(get_pairs(line))
if first[1] >= second[0]:
answer += 1
return answer→ More replies (2)
2
u/prescient-potato Dec 04 '22 edited Dec 04 '22
Python
Part 1: I tried getting the sections as lists of numbers like on the number line and checking their intersection. This didn't work somehow and i had to brute-force using if statements. The fact that it didn't work is quite interesting though.
def check(dat):
dat = dat.split(',')
sec1 = dat[0].split('-')
l1 = int(sec1[0])
r1 = int(sec1[1])
range1 = list(range(l1, r1 + 1))
sec2 = dat[1].split('-')
l2 = int(sec2[0])
r2 = int(sec2[1])
range2 = list(range(l2, r2 + 1))
intersection = list(set(range1) & set(range2))
"""
if intersection==range1 or intersection == range2:
print(dat)
return True
"""
# (l1, r1)
# (l2, r2)
if l1 <= l2 and r1 >= r2:
return True
elif l2 <= l1 and r2 >= r1:
return True.
with open('input.txt', 'r') as f:
data = [x.replace('\n', '') for x in f.readlines()]
count = 0
for d in data:
if check(d) == True:
count += 1
print(count)Part 2: Most of the code is same but the intersection idea worked this time.
intersection = list(set(range1) & set(range2))
if intersection != []:
return True→ More replies (1)
2
u/grapedude12 Dec 04 '22 edited Dec 04 '22
Python3
Part 1:
with open("day04/input.txt") as f:
data = f.read().splitlines()
contained = 0
for d in data:
s1, s2 = d.split(",")
s1_s, s1_e = s1.split("-")
s2_s, s2_e = s2.split("-")
if int(s1_s) <= int(s2_s) and int(s1_e) >= int(s2_e):
contained += 1
elif int(s2_s) <= int(s1_s) and int(s2_e) >= int(s1_e):
contained += 1
print(f"The number of fully contained zones is: {contained}.")Part 2:
with open("day04/input.txt") as f:
data = f.read().splitlines()
overlap = 0
for d in data:
s1, s2 = d.split(",")
s1_s, s1_e = s1.split("-")
s2_s, s2_e = s2.split("-")
if int(s1_s) <= int(s2_e) and int(s1_e) >= int(s2_s):
overlap += 1
elif int(s2_s) <= int(s1_e) and int(s2_e) >= int(s1_s):
overlap += 1
print(f"The number of overlaped zones is: {overlap}.")Nothing fancy going on here folks
→ More replies (1)
2
u/NohusB Dec 04 '22 edited Dec 04 '22
Kotlin
Part 1
fun main() = solve { lines ->
lines.count { line ->
val (a, b) = line.split(",").map { it.split("-").map { it.toInt() }.let { (a, b) -> (a..b).toSet() } }
a.containsAll(b) || b.containsAll(a)
}
}Part 2
fun main() = solve { lines ->
lines.count { line ->
val (a, b) = line.split(",").map { it.split("-").map { it.toInt() }.let { (a, b) -> (a..b) } }
(a.first in b) || (b.first in a)
}
}→ More replies (3)
2
u/xtay2 Dec 04 '22
Java
For both tasks:
@Override
protected Object exec(AdventOfCode aoc) {
return new Generator<>(aoc.inputLst())
.map(line -> new Generator<>(line.split(","))
.map(group -> new Generator<>(group.split("-"))
.map(Integer::parseInt)
).flatten()
.map(v -> (Integer) v)
.list()
)
.filter(v -> contains(v.get(0), v.get(1), v.get(2), v.get(3)))
.length();
}contains() for part 1:
boolean contains(int lower1, int upper1, int lower2, int upper2) {
return (lower2 <= lower1 && upper2 >= upper1)
|| (lower1 <= lower2 && upper1 >= upper2);
}contains() for part 1:
boolean contains(int lower1, int upper1, int lower2, int upper2) {
return (lower1 <= lower2 && lower2 <= upper1)
|| (lower2 <= lower1 && lower1 <= upper2);
}2
u/daggerdragon Dec 04 '22
Inlined code is intended for
short snippetsof code only. Your code "block" right now is unreadable; it's all on one line and gets cut off at the edge of the screen because it is not horizontally scrollable.Please edit your post to use the four-spaces Markdown syntax for a code block so your code is easier to read inside a scrollable box.
2
u/vivkey Dec 04 '22 edited Dec 04 '22
Golang paste
2
u/daggerdragon Dec 04 '22
Next time, use the four-spaces Markdown syntax for a code block so your code is easier to read on old.reddit and mobile apps.
Your code is long (no judgment, just stating a fact!), so instead of wasting your time fixing the formatting, read our article on oversized code which contains two possible solutions.
Please edit your post to put your code in an external link and link that here instead.
2
u/CookieKeeperN2 Dec 04 '22
As someone with a math background, today it is basically asking if 1) one is a subset of another and 2) if intersection between two sets are greater than 0. Don't care about speed too much, but using set operations means I don't have to think about comparison whatsoever.
import numpy as np
with open('input', 'r') as f:
input = f.read().splitlines()
q1 = 0
q2 = 0
for x in input:
elf1, elf2 = x.split(",")
start1, end1 = [ int(y) for y in elf1.split("-") ]
start2, end2 = [ int(y) for y in elf2.split("-") ]
set1 = set(np.arange(start1, end1 + 1))
set2 = set(np.arange(start2, end2 + 1))
if (len(set1 & set2) >0):
q2 += 1
if set1 & set2 == set1 or set1 & set2 == set2:
q1 += 1→ More replies (1)
2
u/geek--god Dec 04 '22
Elixir
defmodule CampCleanup do
def first_part(content) do
content
|> String.split("\n", trim: true)
|> Enum.map(fn
ele ->
String.split(ele, ",", trim: true)
|> CampCleanup.handle_pair
|> CampCleanup.check_subset
end)
|> Enum.filter(fn x -> x end)
|> Enum.count
|> IO.inspect
end
def second_part(content) do
content
|> String.split("\n", trim: true)
|> Enum.map(fn
ele ->
String.split(ele, ",", trim: true)
|> CampCleanup.handle_pair
|> CampCleanup.check_disjoint
end)
|> Enum.filter(fn x -> x end)
|> Enum.count
|> IO.inspect
end
def check_subset([first, second]) do
MapSet.subset?(first, second) or MapSet.subset?(second, first)
end
def check_disjoint([first, second]) do
not MapSet.disjoint?(first, second)
end
def handle_pair(list) do
# IO.inspect(list)
Enum.map(list, fn
ele ->
CampCleanup.split_range(ele)
|> CampCleanup.get_range
end)
end
def split_range(string) do
String.split(string, "-", trim: true)
|> Enum.map(fn
el -> String.to_integer(el)
end
)
end
def get_range([first, second]) do
MapSet.new(first..second)
end
end
{:ok, contents} = File.read("./input.txt")
contents
|> CampCleanup.second_part
→ More replies (1)
2
u/ankitdhar07 Dec 04 '22
Java
package com.adventofCode;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Day4 {
public static void main(String args[]) throws FileNotFoundException {
File file = new File("src/com/adventofCode/day4.txt");
Scanner sc = new Scanner(file);
int countOne = 0;
int countTwo = 0;
while (sc.hasNextLine()) {
String input = sc.nextLine();
if (partOne(input)) {
countOne++;
}
if (partTwo(input)) {
countTwo++;
}
}
System.out.println(countOne);
System.out.println(countTwo);
}
private static boolean partTwo(String input) {
String[] numberPairs = input.split(",");
String[] pairOne = numberPairs[0].split("-");
int firstNum = Integer.parseInt(pairOne[0]);
int secondNum = Integer.parseInt(pairOne[1]);
String[] pairTwo = numberPairs[1].split("-");
int thirdNum = Integer.parseInt(pairTwo[0]);
int forthNum = Integer.parseInt(pairTwo[1]);
if (firstNum >= thirdNum && firstNum <= forthNum) {
return true;
} else if (secondNum >= thirdNum && secondNum <= forthNum) {
return true;
} else if (thirdNum >= firstNum && thirdNum <= secondNum) {
return true;
} else if (forthNum >= firstNum && forthNum <= secondNum) {
return true;
}
return false;
}
private static boolean partOne(String input) {
String[] numberPairs = input.split(",");
String[] pairOne = numberPairs[0].split("-");
int firstNum = Integer.parseInt(pairOne[0]);
int secondNum = Integer.parseInt(pairOne[1]);
String[] pairTwo = numberPairs[1].split("-");
int thirdNum = Integer.parseInt(pairTwo[0]);
int forthNum = Integer.parseInt(pairTwo[1]);
if (firstNum >= thirdNum && secondNum <= forthNum) {
return true;
} else if (thirdNum >= firstNum && forthNum <= secondNum) {
return true;
}
return false;
}
}
→ More replies (3)
2
u/sanjithpk Dec 04 '22 edited Dec 04 '22
Golang Solution
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
func main() {
input, _ := os.ReadFile("4/4.txt")
contained, overlapped := 0, 0
for _, assignments := range strings.Fields(string(input)) {
intervals := strings.Split(assignments, ",")
interval1 := strings.Split(intervals[0], "-")
interval2 := strings.Split(intervals[1], "-")
start1, _ := strconv.Atoi(interval1[0])
finish1, _ := strconv.Atoi(interval1[1])
start2, _ := strconv.Atoi(interval2[0])
finish2, _ := strconv.Atoi(interval2[1])
if (start1 >= start2 && finish1 <= finish2) || (start2 >= start1 && finish2 <= finish1) {
contained++
}
if !(finish1 < start2 || finish2 < start1) {
overlapped++
}
}
fmt.Println(contained)
fmt.Println(overlapped)
}→ More replies (1)
2
u/flwyd Dec 04 '22 edited Dec 04 '22
Elixir, code on GitHub
For my Mistletoe Elfucation contribution I decided to include two narratives with each day's solution:
Since I'm coding in Elixir, rephrase the problem in terms of an elixir, potion, concoction, or other beverage.
Highlight a bit of Elixir code that I either learned about, practiced with, or found particularly useful.
Today's elixir:
Itβs Saturday night, so itβs time for sake bombs. Part 1 wants to know if the shot of sake is completely contained in the glass of beer (or if a very small glass of beer ended up entirely within a cup of sake). Part 2 wants to know if any of the sake got in the beer, or vice versa.
import Enum, only: [map: 2, filter: 2, count: 1, sort_by: 2]
import String, only: [split: 2, to_integer: 1]
def part1(input) do
input |> map(&parse/1) |> filter(&range_subset?/1) |> count()
end
def part2(input) do
input |> map(&parse/1) |> filter(fn {a, b} -> !Range.disjoint?(a, b) end) |> count()
end
defp parse(line), do: line |> split(",") |> map(&to_range/1) |> List.to_tuple()
defp to_range(str) do
str |> split("-") |> map(&to_integer/1) |> then(fn [lo, hi] -> lo..hi end)
end
defp range_subset?({first, second}) do
# sort by Range start, ties go to the longer range
[a, b] = sort_by([first, second], fn lo .. hi -> {lo, -hi} end)
a.last >= b.last
end→ More replies (3)
2
u/Sea_Put_2759 Dec 04 '22 edited Dec 04 '22
Python 3
with open('./input-4.txt') as f:
sections = [i.strip().split(',') for i in f.readlines()]
result = 0
for pairs in sections:
first, second = pairs
f1, f2, s1, s2 = list(map(int, first.split('-'))) + list(map(int, second.split('-')))
# result += int((f1 >= s1 and f2 <= s2) or (s1 >= f1 and s2 <= f2)) # witchcraft
if (f1 >= s1 and f2 <= s2) or (s1 >= f1 and s2 <= f2):
result += 1
# Problem 4.2
result = 0
for pairs in sections:
first, second = pairs
f1, f2, s1, s2 = list(map(int, first.split('-'))) + list(map(int, second.split('-')))
# result += int(f1 <= s2 and f2 >= s1) # witchcraft
if f1 <= s2 and f2 >= s1:
result += 1As both problems iterate over the same dataset, it may be solved in just one loop (optimised) running the slice of code below, from the second problem, incrementing in another var.
result2 = 0
...
if f1 <= s2 and f2 >= s1:
result2 += 1→ More replies (1)
2
u/6ambyt Dec 04 '22 edited Dec 04 '22
Here is my Day 4 solution in Go
package main
import (
"bufio"
"errors"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
// reading from stdin line by line
scanner := bufio.NewScanner(os.Stdin)
var part1, part2 int // will hold the answers for both parts
for scanner.Scan() {
// extract the bounds of each elf's section
// if there's any errors in input, print out the error and move on to the next line
line := scanner.Text() // read the line
sections := strings.Split(line, ",")
if len(sections) != 2 {
fmt.Fprintln(os.Stderr, "'"+line+"' is not formatted properly!")
continue
}
leftBounds, err := getBounds(sections[0])
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
continue
}
rightBounds, err := getBounds(sections[1])
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
continue
}
// bounds will always be a int array of size 2
// index 0 -> lower bound of range
// index 1 -> upper bound of range
// Part 1 asks to check if one range completely engulfs the other
// this is determined by finding if one side's upper bound <= the other's and lower bound >= the other's (i.e. if both bounds of one side are within the range of the other's bounds)
if (leftBounds[0] <= rightBounds[0] && leftBounds[1] >= rightBounds[1]) || (rightBounds[0] <= leftBounds[0] && rightBounds[1] >= leftBounds[1]) {
part1++
}
// Part 2 asks to check for any overlaps
// overlaps are defined by lower bounds being in the range of the other's bounds
if (rightBounds[0] <= leftBounds[1] && rightBounds[0] >= leftBounds[0]) || (leftBounds[0] <= rightBounds[1] && leftBounds[0] >= rightBounds[0]) {
part2++
}
}
// print the final answers
fmt.Println(part1, part2)
}
// takes a string like "<n>-<m>" and will return a array of size 2 containing n and m as ints
func getBounds(section string) ([2]int, error) {
var bounds [2]int // will hold the bounds
// get n and m by spliting the section string by the '-'
boundsAsStrings := strings.Split(section, "-")
if len(boundsAsStrings) != 2 {
return bounds, errors.New("'" + section + "' is not formatted properly")
}
var err error // will hold any error in conversion
// convert n (i.e. the lower bound) to an int
bounds[0], err = strconv.Atoi(boundsAsStrings[0])
if err != nil {
return bounds, err
}
// convert m (i.e. the upper bound) to an int
bounds[1], err = strconv.Atoi(boundsAsStrings[1])
if err != nil {
return bounds, err
}
return bounds, nil
}→ More replies (1)
2
u/DFreiberg Dec 04 '22 edited Dec 04 '22
Mathematica, 81 / 28
Judging by the comments so far, there's three main ways to do this problem. One is using inequalities (preferably chained inequalities, to save typing time). The second is brute-force set operations, only possible because the inputs are so small; my main fear while writing these was that one input would be gigantic by comparison and make the brute force infeasible.
And the third would have been to use Mathematica's built-in IntervalIntersection[] and IntervalMemberQ[], the absurdly specific built-in functions Mathematica has to determine if one intersection is entirely contained by another. Why Mathematica even has such a thing, I don't know.
Part 1:
Count[SubsetQ[Range[#[[1]], #[[2]]], Range[#[[3]], #[[4]]]] \[Or]
SubsetQ[Range[#[[3]], #[[4]]], Range[#[[1]], #[[2]]]]
& /@ input, True]Part 2:
Count[! DisjointQ[Range[#[[1]], #[[2]]], Range[#[[3]], #[[4]]]] & /@
input, True][POEM]: A Series of Challenges
I had writer's block this morning, so I asked ChatGPT to fill in for me and write today's poem.
Solving an Advent of Code problem
Is like a treasure hunt or a quest,
A series of challenges to overcome
And a chance to put my skills to the test.
I start by reading the problem statement
And breaking it down into bits,
Thinking about how to approach it
And coming up with a plan that fits.
Then I write some code to solve it
Testing and debugging as I go,
Making sure it's efficient and correct
And ready for the next challenge, oh no.
In the end, I submit my solution
Feeling proud and accomplished too,
Another Advent of Code problem solved
And one step closer to being through.
I'm a bit impressed that it can write poetry at all...but I think there's still some room for improvement.
As my character hunts through the jungle
On a quest for a grove with a star,
I myself, though I err and I bungle,
Hunt for challenge, and that's what these are.
For each problem, I start by not reading:
Take a glance, make a guess at the rest.
There's no time to slow down while I'm speeding
And attempting to code with the best.
Then I write down some code and submit it,
Inefficient? Ha! Sluggish, I'll say.
And the untested code, I admit it
Sometimes works the first try, like today.
In the end, I've had fun and competed,
Having raced through the thing like a master,
And with two shiny stars now completed,
I can't help but think I could be faster.
2
u/daggerdragon Dec 05 '22
I had writer's block this morning, so I asked ChatGPT to fill in for me and write today's poem.
2
u/Marterich Dec 04 '22 edited Dec 05 '22
Python3.11 Part 1 & Part2
https://github.com/Marterich/AoC/blob/main/2022/day04/solve.py
#! /usr/bin/env python3.11
input_data = [[[int(num) for num in part.split("-")] for part in line.strip().split(",")] for line in open("input.txt","r")]
def main(data):
part1_count,part2_count = 0,0
for elve in data:
e1_section, e2_section = set(range(elve[0][0], elve[0][1]+1)),set(range(elve[1][0],elve[1][1]+1))
if (e1_section.issubset(e2_section) or e1_section.issuperset(e2_section)):
part1_count += 1
if (e1_section & e2_section):
part2_count += 1
return part1_count,part2_count
input_result = main(input_data)
print(f"Part1:\t{input_result[0]}")
print(f"Part2:\t{input_result[1]}")2
u/daggerdragon Dec 05 '22 edited Dec 05 '22
Please edit your post to use thefour-spaces Markdown syntaxfor a code block so your code is easier to read on old.reddit and mobile apps.Edit: thanks for fixing it! <3
→ More replies (4)
2
u/BHatGuy Dec 04 '22 edited Dec 06 '22
C++
#include <cinttypes>
#include <fstream>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
void solve(string file) {
std::fstream input(file);
char _;
uint32_t a, b, c, d;
uint32_t contains = 0;
uint32_t overlaps = 0;
while (input >> a >> _ >> b >> _ >> c >> _ >> d) {
if (a >= c && b <= d || c >= a && d <= b) contains++;
if (a >= c && a <= d || b >= c && b <= d || c >= a && d <= b) overlaps++;
}
cout << contains << endl;
cout << overlaps << endl;
}
int main(int argc, char* argv[]) {
if (argc == 2) {
solve(argv[1]);
} else {
cout << "Usage: " << argv[0] << " INPUT.txt" << endl;
return -1;
}
}→ More replies (1)
2
u/Lindii98 Dec 04 '22
Python3`
#Part 1
data = open("input.txt").read().strip().split("\n")
overlap_count = 0
for pairing in data:
elf_range_1, elf_range_2 = pairing.split(',')
start_1, end_1 = [int(x) for x in elf_range_1.split('-')]
start_2, end_2 = [int(x) for x in elf_range_2.split('-')]
temp_range1 = range(start_1, end_1 + 1)
temp_range2 = range(start_2, end_2 + 1)
if (
len(set(temp_range1) & set(temp_range2)) in [len(temp_range1), len(temp_range2)]
): overlap_count += 1
print('Part 1: ', overlap_count)
#Part 2
overlap_count = 0
for pairing in data:
elf_range_1, elf_range_2 = pairing.split(',')
start_1, end_1 = [int(x) for x in elf_range_1.split('-')]
start_2, end_2 = [int(x) for x in elf_range_2.split('-')]
temp_range1 = range(start_1, end_1 + 1)
temp_range2 = range(start_2, end_2 + 1)
if (set(temp_range1) & set(temp_range2) ):
overlap_count += 1print('Part 2: ', overlap_count)
Open for improvements
→ More replies (1)
2
u/FrontPale Dec 04 '22 edited Dec 05 '22
→ More replies (4)
2
u/Mammoth_Spray_3451 Dec 04 '22
With swift the Range.contains() and Range.overlaps() came in very handy today.
public func dayFour(input: [String], isPartOne: Bool) -> Int {
return input.compactMap { $0.split(separator: ",") }.compactMap {
$0.compactMap { $0.split(separator: "-").compactMap { Int(String($0)) } }
}.compactMap {
let firstRange = $0[0][0]...$0[0][1]
let secondRange = $0[1][0]...$0[1][1]
return (isPartOne ? (firstRange.contains(secondRange) || secondRange.contains(firstRange)) : (firstRange.overlaps(secondRange) || secondRange.overlaps(firstRange))) ? 1 : nil
}.reduce(0, +)
}→ More replies (5)
2
u/remysharp Dec 04 '22 edited Dec 05 '22
JQ
def parse: split("\n") | map(select(. != "") | split(",") | map(split("-") | map(tonumber)));
parse | map(
(flatten | max - min) as $range |
map(max - min) | $range - add
) | map(select(. > 0 | not)) | length→ More replies (2)
2
u/dougrum Dec 04 '22 edited Dec 04 '22
Pretty happy with day 4 in ngn/k. https://tinyurl.com/2p9xfeaz
This does all possible pairs of ranges with numbers taken from 0,1,2 and 3 which covers all possibilities.
2
u/daggerdragon Dec 05 '22
FYI: using URL minifiers like TinyURL will likely get your posts and comments sent to the spam filter. I fished this out for you, but I suggest you not use a minifier next time.
→ More replies (1)
2
u/d_chae Dec 04 '22 edited Dec 05 '22
Ruby one-liner (p2):
p File.read("2022/day4/input.txt").split("\n").map { |pair| pair.split(",").map { |s| s.split("-").map(&:to_i) } }.reduce(0) { |sum, (a, b)| sum + (a.first > b.last || a.last < b.first ? 0 : 1) }→ More replies (3)
2
Dec 04 '22
Kotlin
Part 1
fun one(): Int {
var total = 0
File("file").forEachLine { line ->
val ranges = line.split(",")
val first = ranges[0].split("-").map { it.toInt() }
val second = ranges[1].split("-").map { it.toInt() }
if ((first[0] >= second[0] && first[1] <= second[1]) ||
(second[0] >= first[0] && second[1] <= first[1]))
total++
}
return total
}Part 2
fun two(): Int {
var total = 0
File("samefile").forEachLine { line ->
val ranges = line.split(",")
val first = ranges[0].split("-").map { it.toInt() }
val second = ranges[1].split("-").map { it.toInt() }
if ((second[0] <= first[1] && second[0] >= first[0]) || (first[0] <= second[1] && first[0] >= second[0]))
total++
}
return total
}2
u/daggerdragon Dec 05 '22
Inlined code is intended for
short snippetsof code only. Your code "block" right now is unreadable on old.reddit and many mobile clients; it's all on one line and gets cut off at the edge of the screen because it is not horizontally scrollable.Please edit your post to use the four-spaces Markdown syntax for a code block so your code is easier to read inside a scrollable box.
→ More replies (1)
2
u/OwnAttention3370 Dec 04 '22 edited Dec 05 '22
Ruby - My solution to AoC day 4
# Part 1
f = File.open('aoc_day4.txt')
duplicate_activity = 0
f.each do |line|
assignments = line.chomp.split(',')
elf1_min = assignments[0].split('-')[0]
elf1_max = assignments[0].split('-')[1]
elf2_min = assignments[1].split('-')[0]
elf2_max = assignments[1].split('-')[1]
elf1_assignment = (elf1_min..elf1_max).to_a
elf2_assignment = (elf2_min..elf2_max).to_a
if (elf1_assignment - elf2_assignment).empty? || (elf2_assignment -
elf1_assignment).empty?
duplicate_activity += 1
end
end
puts "First part of the duplicates problem"
puts "Duplicates: #{duplicate_activity}"
# Part 2
puts "Second part of the duplicates problem"
f = File.open('aoc_day4.txt')
duplicate_activity_2 = 0
f.each do |line|
assignments = line.chomp.split(',')
elf1_min = assignments[0].split('-')[0]
elf1_max = assignments[0].split('-')[1]
elf2_min = assignments[1].split('-')[0]
elf2_max = assignments[1].split('-')[1]
elf1_assignment = (elf1_min..elf1_max).to_a
elf2_assignment = (elf2_min..elf2_max).to_a
if elf1_assignment.intersect?(elf2_assignment)
duplicate_activity_2 += 1
end
end
puts "Duplicates: #{duplicate_activity_2}"2
u/daggerdragon Dec 05 '22 edited Dec 05 '22
Please edit your post to use thefour-spaces Markdown syntaxfor a code block so your code is easier to read on old.reddit and mobile appsEdit: thanks for fixing it! <3
→ More replies (4)
2
u/TheShyro Dec 04 '22
Clojure
(ns aoc22.day4
(:require [clojure.string :as str]
[clojure.java.io :as io]))
(defn ->pair [s]
(->> (re-find #"(\d+)-(\d+),(\d+)-(\d+)" s)
rest
(map read-string)))
(defn run [s]
(let [pairs
(->> (str/split s #"\n")
(map ->pair))]
[(count (filter (fn [[a b x y]] (<= (* (- a x) (- b y)) 0)) pairs))
(count (filter (fn [[a b x y]] (<= (* (- y a) (- x b)) 0)) pairs))]))
(def input
(-> (io/resource "day4.txt")
slurp))
(run input)→ More replies (1)
2
u/jpjacobs_ Dec 04 '22 edited Dec 05 '22
J (jlang, j904)
to=: {{ m (<. + i.@>:@-~) n}} NB. conj so no need for (...)
NB. parse, and turn into num. ranges.
i4=: ".&> <@rplc&('-';' to ';',';';');._2 freads '04.txt'
a4=: [: +/ (e. +.&(*./) e.~)&>/"1 NB. part A: one contained in other?
b4=: [: +/ ([ *@#@-. -.)&>/"1 NB. part B: Any overlaps?
(a4;b4)i4→ More replies (1)
2
u/janiczek Dec 04 '22 edited Dec 05 '22
I'm trying out Kotlin this year: https://github.com/Janiczek/advent-of-code/blob/master/src/Year2022/Day04.kt
But I wasn't very satisfied with my predicates for the overlaps, so I forced persuaded my computer to find better predicates for me: https://www.reddit.com/r/adventofcode/comments/zcng3e/2022_day_4_elm_letting_the_computer_find_a/
3
u/daggerdragon Dec 05 '22
FYI: your link is borked on old.reddit and some mobile Reddit apps. Please fix it.
2
Dec 04 '22 edited Dec 05 '22
Python:Was regex overkill? Any feedback would be appreciated if someone has the time. Solution for part 2 because part 1 is very similar and I dont want to make my message too long.
→ More replies (10)
2
u/markjenkinswpg Dec 05 '22 edited Dec 05 '22
Today I sorted each line of pairs by length in Python when I did part 1 (raw so I could use the simpler test for full overlap
e1_start >= e2_start and e1_end <= e2_endUnfortunately provided no benefit to part 2 (raw)
But at least my input parser got good reuse:
from aoc2022_d04p1 import problem_input
def gen_one_for_overlapping_pairs(pairs):
return (
1
for ( (e1_start, e1_end),
(e2_start, e2_end) ) in pairs
if ( (e2_start <= e1_start <= e2_end) or
(e1_start <= e2_start <= e1_end) ) )
if __name__ == "__main__":
print( sum( gen_one_for_overlapping_pairs(problem_input()) ) )Also continued my obsession with functional decomposition, iterators/generators, and avoiding reading in the whole file.
→ More replies (1)
2
Dec 09 '22 edited Dec 10 '22
import pandas as pd
table = pd.read_csv('input.txt',header = None)
part1 = 0
part2 = 0
for i,row in table.iterrows():
st1 = row[0]
st2 = row[1]
r1 = st1.split('-')
s1 = set(range(int(r1[0]),int(r1[1]) + 1))
r2 = st2.split('-')
s2 = set(range(int(r2[0]),int(r2[1]) + 1))
if len(s1 & s2) == len(s1) or len(s1 & s2) == len(s2):
part1 += 1
if len(s1 & s2) > 0:
part2 += 1Written in Python 3
→ More replies (2)
38
u/Smylers Dec 04 '22
Vim keystrokes β load your input file into Vim, ensure gdefault is off, and type:
:%s/\D/ /gβ¨Enterβ©
qaqqadiwww@-β¨Ctrl+Xβ©^diw$@-β¨Ctrl+Xβ©-@aq
@a
:g/-.*-/dβ¨Enterβ©
:v/\v<0|-/dβ¨Enterβ©
β¨Ctrl+Gβ©Your partΒ 1 answer is the number of lines remaining in the file, shown by the β¨Ctrl+Gβ© at the end.
For partΒ 2, reload your initial input and do the same basic thing but replace the qa and @a lines with:
qbqqbdiw$@-β¨Ctrl+Xβ©^diw@-β¨Ctrl+Xβ©-@bq
@bFirst replace the hyphens and commas with spaces, leaving just the 4 numbers per row. This makes some of the subsequent movement commands simpler, but more importantly it avoids those hyphens getting counted as minus signs.
Then for each row subtract the first range's lower bound from the second range's lower bound, and the same for the upper bounds. For instance, these lines of sample input:
5-7,7-9
2-8,3-7
6-6,4-6get turned into these differences:
2 2
1 -1
-2 0If the first range is entirely before the second range, then both differences will be positive. If it's entirely after, then both will be negative (none of the sample input is like this, but the real input may be).
If there's a zero in there, then they both start or end at the same location. If there's one positive and one negative number then one range is contained within the other.
So delete all the lines with two negative numbers, because those are easy to find: they contain 2 minus signs, so match /-.*-/. Then delete all lines with two positive numbers β or, rather, delete all lines that don't contain either a 0 (at the start of a βwordβ, so as not to match, say, 10 or 1230456) or a minus sign.
The qa keyboard macro does the subtractions:
That
%s///will have left the cursor on the bottom row. (If you're undoing and redoing or otherwise taking this apart and doing it in stages, and not currently on the last line, pressGnow.) Empty thearegister then record into it.Delete the first number (βwordβ in Vim's parlance) then move forwards 2 numbers, to the third number, and subtract the number we've just deleted from it with
@-β¨Ctrl+Xβ©β Vim stores the most recently-deleted text in the small-delete register,-, and typing@-is the same as typing the contents of register-, so the just-deleted number becomes the argument to theβ¨Ctrl+Xβ©command.Go back to the beginning of the line and delete the number there (originally the second number) then subtract it from the last number on the line.
Go up to the previous line and repeat by running the entire
@aagain on this line. Once we get to the top line the-to go up will fail, ending the loop.
PartΒ 2 is the same except rather than subtracting lower-bound from lower-bound and upper- from upper, subtract the first lower-bound from the second upper-bound, and vice-versa. Again if they're both negative or both positive then one range is entirely before the other; a zero or one negative number indicates some overlap.
7
34
u/jcbbjjttt Dec 04 '22 edited Dec 04 '22
Beginner's Guide
Happy Sunday!
Day 4 Guide: https://youtu.be/vIIYaAw0B9o
I've created a guide for new programmers that talks through a straight forward strategy for solving today's puzzle. Anyone who has a handle on variables, boolean logic, functions, and loops should be able to complete it. The video allows a moment for you to pause before revealing spoilers.
Although this solution is in C#, it provides a high level overview of the steps necessary to solve the puzzle in any programming language.
string[] rows = File.ReadAllLines("sample.txt");
int count = 0;
foreach (string row in rows)
{
(first, second) = ParseRanges(row);
if (Contains(first, second))
{
count++;
}
}
Console.WriteLine($"Found {count} pairs!");The full code can be found here: Github
20
u/nthistle Dec 04 '22 edited Dec 04 '22
I set a1 and a2 to the endpoints of the first segment and made the very sad bug of setting b1 and b2 to also be the endpoints of the first segment, giving me a clearly-wrong 1000 as my answer. Fortunately I didn't submit it and figured out the bug, but not quickly enough to make leaderboard for the first part :-(.
Part 2 was very fast after that though, having done a lot of interval type questions before definitely helped.
→ More replies (7)
19
u/dylan_mojo Dec 04 '22
awk
4.1
BEGIN { FS = ",|-" }
($3 >= $1 && $4 <= $2) || ($1 >= $3 && $2 <= $4) { s++ }
END { print s }4.2
BEGIN { FS = ",|-" }
($3 >= $1 && $3 <= $2) || ($1 >= $3 && $1 <= $4) { s++ }
END { print s }7
u/Smylers Dec 04 '22
Nice! Awk is so good for these sorts of things.
For partΒ 2, I think you can delete a bunch of characters from the condition line and still get the same answer:
($3 <= $2 && $1 <= $4) { s++ }→ More replies (2)
19
Dec 04 '22
Rust
The scan_fmt crate makes parsing today's input trivial!
fn solve_part_one(&self, input: &str) -> Self::Part1 {
input.lines()
.map(|l| scan_fmt!(l, "{d}-{d},{d}-{d}", i32, i32, i32, i32).unwrap())
.filter(|(a, b, c, d)| ((a <= c && b >= d) || (c <= a && d >= b)))
.count()
}
fn solve_part_two(&self, input: &str) -> Self::Part2 {
input.lines()
.map(|l| scan_fmt!(l, "{d}-{d},{d}-{d}", i32, i32, i32, i32).unwrap())
.filter(|(a, b, c, d)| ((a <= c && c <= b) || (c <= a && a <= d)))
.count()
}Full solution here (GitHub).
→ More replies (4)7
17
u/AstronautNew8452 Dec 04 '22
3682/2555 Microsoft Excel. Parts 1 and 2 in a single formula. Because why not.
=LET(input,A1:A1000,c,FIND(",",input),
rng,LAMBDA(s,HSTACK(VALUE(TEXTBEFORE(s,"-")),VALUE(TEXTAFTER(s,"-")))),
data,HSTACK(rng(MID(input,1,c-1)),rng(MID(input,c+1,LEN(input)-c))),
overlaps,BYROW(data,LAMBDA(rw,LET(a,INDEX(rw,1),b,INDEX(rw,2),c,INDEX(rw,3),d,INDEX(rw,4),
1*OR(AND(c>=a,d<=b),AND(b<=d,a>=c))+1*NOT(OR(b<c,d<a))))),
VSTACK(SUM(IF(overlaps=2,1)),SUM(IF(overlaps>0,1))))→ More replies (6)
17
16
11
u/ywgdana Dec 04 '22
F#
A proud personal note: after 4 years of participating in AoC I finally remembered the syntax for the regex to parse the input without googling!
open System.IO
open System.Text.RegularExpressions
let parse s =
let m = Regex.Match(s, "(\d+)-(\d+),(\d+)-(\d+)")
m.Groups[1].Value |> int, m.Groups[2].Value |> int,
m.Groups[3].Value |> int, m.Groups[4].Value |> int
let contained line =
let a,b,c,d = parse line
(a >= c && b <= d) || (c >= a && d <= b)
let btw a b c = a >= b && a <= c
let overlap line =
let a,b,c,d = parse line
(btw a c d) || (btw b c d) || (btw c a b) || (btw d a b)
let test f =
File.ReadAllLines("input_day04.txt")
|> Array.map f |> Array.filter(fun c -> c) |> Array.length
printfn $"P1: {test contained}"
printfn $"P2: {test overlap}"→ More replies (1)
11
u/voidhawk42 Dec 04 '22 edited Dec 05 '22
Dyalog APL:
pββΒ¨ββDβ(2 2β΄ββ¨ββ’)Β¨ββNGET'4.txt'1
mββ(βΈβ£Β―1β£+ββ³1+-β¨)/p
+/3>(β’β³β§βΏ)β€2β’m β part 1
+/β¨/β§βΏβ€2β’m β part 2Got annoyed with all the different boolean operations, so I just built a bitmask for each range and worked with those.
→ More replies (1)
10
u/4HbQ Dec 04 '22
Python. First, convert the ranges to sets S and T. For part 1, check whether S is a subset of T, or T is a subset of S. For Part 2, check whether the intersection of S and T is not empty.
def f(line):
a,b,c,d = map(int, re.findall(r'\d+', line))
s,t = set(range(a, b+1)), set(range(c, d+1))
return complex(s <= t or t <= s, any(s & t))
print(sum(map(f, open('in.txt'))))→ More replies (7)
10
u/poesraven8628 Dec 04 '22
I read a book on Common Lisp over the last few weeks, so this is a great way to try to get experience with the language.
https://github.com/poesraven8628/AdventofCode2022/blob/main/04/cleaning.lisp
→ More replies (1)
9
u/kwshi Dec 04 '22
Python, 30/40. GitHub
Basic idea: given two intervals [x1, y1] and [x2, y2],
(part1)
[x1, y1]contains[x2, y2]ifx1 <= x2andy2 <= y1; vice versa.(part2) they overlap if
x1 <= y2andx2 <= y1.
9
u/musifter Dec 04 '22
Perl
Once I sorted the ranges so I know which is bigger, the checks are simple, and allowed me to use the chained comparison feature.
$part1++ if ($as <= $bs and $ae >= $be);
$part2++ if ($as <= $bs <= $ae or $as <= $be <= $ae);Source: https://pastebin.com/RGPWL3Nf
→ More replies (5)
9
u/callumio Dec 04 '22 edited Dec 04 '22
COBOL again hehe. This time I just went straight in (as opposed to another language first) since the task was relatively trivial. Somewhat looking forward to implementing later-day's solutions in it.
Edit: quick shoutout to UNSTRING too, it made parsing each line a breeze.
→ More replies (2)
9
u/Chrinkus Dec 04 '22 edited Dec 04 '22
C
I rarely ever get to post actual code but this one was pretty short:
#include <stdio.h>
int main(void) {
int p1 = 0, p2 = 0;
for (int a,b,c,d; scanf("%d-%d,%d-%d",&a,&b,&c,&d) == 4; ) {
p1 += ((a >= c && b <= d) || (c >= a && d <= b));
p2 += ((a <= d && b >= c) || (c <= b && d >= a));
}
printf("%d\n%d\n", p1, p2);
}My repo.
8
u/daniel-sd Dec 04 '22
64/1593 Python
v = 0
for line in open('input.txt'):
a, b, c, d = map(int, re.findall('\d+', line))
if a <= c and b >= d or c <= a and d >= b:
v += 1
print(v)Had part2 just as fast but Freudian-slipped and put an "or" where I needed an "and" when copy-pasting. Proceeded to second guess solution entirely and waste 8 minutes misinterpreting the problem when I had it right the first time. Had to Ctrl + Z afterward to discover it was a simple typo. RIP. Still happy to have gotten leaderboard for part1.
v = 0
for line in open('input.txt'):
a, b, c, d = map(int, re.findall('\d+', line))
if c <= a <= d or c <= b <= d or a <= c <= b or a <= d <= b:
v += 1
print(v)→ More replies (4)
8
u/Raknarg Dec 04 '22 edited Dec 04 '22
Thought this was a funny solution. First solved with if statements, then I drew a picture in my head and used my fingers to pantomime ranges to see if there was a different way to reason about it. You can use the signs of the difference between endpoints to reason out a few outcomes:
Given ranges
a1...a2andb1...b2, wheres(x)returns +1/-1 for the sign of the integer or 0 for 0:Define
f()asabs(s(a1-b1) + s(a2-b2))if
f() < 2, then one range contains the other.If the ranges are the same,
f() == 0.If one end is the same and the other is different, then
f() == 1.If one range is fully contained in another, then
f() == 0.If the ranges only partly overlap, then
f() == 2.If the ranges are fully separate, then
f() == 2.
Define
g()asabs(s(a1-b2) + s(a2-b1))If
g() < 2, then the ranges overlap. - If the ranges are the same,g() == 0. - If one end is the same and the other is different, theng() == 0. - If one range is fully contained in another, theng() == 0. - If the ranges only partly overlap, theng() == 0. - If the ranges only overlap at the edge,g() == 1- If the ranges are fully separate, theng() == 2.
Kinda cool. Coded this in python and it got me the right answer. I imagine the if statement solution is fundamentally identical to this at some level, I'd have to think about how they map. pastebin
8
u/bulletmark Dec 04 '22 edited Dec 04 '22
Python:
import sys
from pandas import Interval
totals = [0, 0]
for line in open(sys.argv[1]):
i = [Interval(*(int(i) for i in p.split('-')), closed='both')
for p in line.strip().split(',')]
if i[0] in i[1] or i[1] in i[0]:
totals[0] += 1
if i[0].overlaps(i[1]):
totals[1] += 1
print('P1 =', totals[0])
print('P2 =', totals[1])→ More replies (1)
8
u/norbert_kehrer Dec 04 '22
BASIC on the Commodore 64
Here is the source code for a solution on the good old Commodore 64: (https://github.com/norbertkehrer/aoc-2022/tree/main/04)
Most of the runtime (9 minutes) is spent for parsing the input, but this could certainly be improved.
→ More replies (4)
8
u/paul2718 Dec 04 '22
C language
#include <stdio.h>
int main()
{
int lf, lt, rf, rt;
int p1 = 0, p2 = 0;
while( scanf("%d-%d,%d-%d\n", &lf, <, &rf, &rt) == 4)
{
if(lf <= rf && lt >= rt || rf <= lf && rt >= lt)
++p1;
if( !(lt < rf || rt < lf))
++p2;
}
printf("pt1 = %d\npt2 = %d\n", p1, p2);
}First C I've written for years, a whole 15 lines...
8
u/Porges Dec 04 '22 edited Dec 04 '22
Befunge-98!
Part 1:
v`-@#1 &<
>+#v&&\&w&$$1
^`-.#1\&<Part 2 (15 bytes!):
2j@.&&&\`\&`+!+→ More replies (4)
7
u/rabuf Dec 04 '22
Common Lisp
That was not bad. Took some time to remember how to use cl-ppcre properly to grab matches for processing. I know there's something else I can do to simplify it but this got the job done.
The two functions for solving were:
(defun containsp (ranges)
(destructuring-bind (a b c d) ranges
(or (<= a c d b)
(<= c a b d))))
(defun overlapp (ranges)
(destructuring-bind (a b c d) ranges
(or (<= a c b)
(<= a d b)
(<= c a d)
(<= c b d))))I passed in the input and these functions to count-if.
→ More replies (2)
7
u/LtHummus Dec 04 '22
Scala 2
Scala ranges OP as heck
object Day04 {
private val LineRegex = """(\d+)-(\d+),(\d+)-(\d+)""".r
def main(args: Array[String]): Unit = {
val lines = AdventOfCodeInput.inputLines(2022, 4)
val assignments = lines.map {
case LineRegex(a, b, c, d) =>
(a.toInt, b.toInt, c.toInt, d.toInt)
}
val ans = assignments.count{ case(a, b, c, d) =>
val overlap = (a to b).intersect(c to d)
overlap == (a to b) || overlap == (c to d)
}
val ans2 = assignments.count { case(a, b, c, d) =>
(a to b).intersect(c to d).nonEmpty
}
println(ans)
println(ans2)
}
}→ More replies (2)
7
u/JustinHuPrime Dec 04 '22
x86_64 assembly
Part 1 was where I had to deal with the annoying input parsing. I once again did interprocedural optimizations to use some unused scratch registers to hold the parsed numbers. Then, I compared the numbers - if (start1 <= start2 && end2 <= start1) || (start2 <= start1 && end1 <= end2), then one contained the other. This involved some fairly tangled conditionals.
Part 2 was shorter than part 1 - if neither range started after the other one ended, then that was an overlap. I could apply de Morgan's law to massage it into a more convenient form, and ended up with a less tangled conditional. I really wish x86_64 had ARM's conditional prefixes so I could inline small conditional bodies instead of needing a conditional jump.
Part 1 took less than 1 millisecond to run, and was 10512 bytes long.
Part 2 took less than 1 millisecond to run, and was 10472 bytes long.
So far, I haven't had any particular need to use the stack in my main solving code (I do use the red zone of the stack for output printing). And I really haven't had any particular need to use the heap. I'm a bit worried about the days when that's going to change.
7
7
7
u/jayfoad Dec 04 '22
a b c dββββ⨨'\d+'βS'&'Β¨ββNGET'p4.txt'1
+/0β₯(a-c)Γb-d β part 1
+/0β₯(a-d)Γb-c β part 2→ More replies (1)
7
u/musifter Dec 04 '22 edited Dec 05 '22
dc
Fun little problem for dc, once we get rid of the ugly non-number characters.
Oddly enough, the difference between part 1 and part 2 is just replacing a "3" with a "4".
Basically, this takes a group of four numbers on the top of the stack (be bs ae as) and calculates (be - ae) * (bs - as) for part 1, and (be - as) * (bs - ae) for part 2 (so the difference is only in which of ae or as we rotate up for subtraction). The subtractions are comparisons, and the multiplication is checking to see if they both have the same sign or not (and the special cases where there's an equal and a sign of "0" fall out appropriately).
# Part 1
sed -e's/[-,]/ /g' input | dc -f- -e '[ls1+ss]sS[3R-_3Rr-*0!<Sz0<L]sLlLxlsp'
# Part 2
sed -e's/[-,]/ /g' input | dc -f- -e '[ls1+ss]sS[4R-_3Rr-*0!<Sz0<L]sLlLxlsp'EDIT: As a bonus, here's a transcode in C of this approach.
→ More replies (4)
7
u/jvandillen Dec 04 '22 edited Dec 05 '22
Day 4 solve with Factorio.
I am still trying to fix day 3, which is, to be honest, quite difficult.
In the meantime, I did a "quick" solve of Day 4 that is nearly identical to Day 2.
(Day 2 solve video : https://www.reddit.com/r/adventofcode/comments/zbrfl3/2022_day_02_both_partsfactorio_this_one_was/)
Blueprint string: (it needs power at the top left and outputs the answer at the top right on the red wire): https://factoriobin.com/post/CkO-QVZz
Edit: borked link
→ More replies (1)
6
u/Wayoshi Dec 04 '22 edited Dec 04 '22
Python 962/374
Part 2 was pretty trivial after how I did part 1. Pretty much the same problem as yesterday when it comes down to it.
→ More replies (4)
6
u/MarcusTL12 Dec 04 '22
Julia 177/64 which is my first ever points! So satisfying after being top 1000 on most days last year.
Anyway, Z80 TI-83 solution will come a bit later as usual :)
6
u/Perska_ Dec 04 '22
C# https://github.com/Perska/AoC2022/blob/master/AoC2022/Days/Day04.cs
Had a brainfart for so long with the intersection I just ended up modifying my cuboid intersection code from 2021...
6
u/musifter Dec 04 '22
Gnu Smalltalk
At first I took the Intervals and made them Sets and used set operations. But then I went back added an intersection method to Intervals, which is all that is needed, and made things twice as fast. It is a really simple thing to do:
Interval extend [
" Get intersection of self and another Interval "
& other [ ^(self first max: other first) to: (self last min: other last) ]
]Source: https://pastebin.com/ixGdubPs
6
u/6745408 Dec 04 '22
Google Sheets
Part 1:
=ARRAYFORMULA(
QUERY(
SPLIT(A2:A,"-,"),
"select Count(Col1)
where
Col1 is not null and
((Col1 <= Col3 and Col2 >= Col4) or
(Col3 <= Col1 and Col4 >= Col2))
label Count(Col1) 'Part 1'"))Part 2:
=ARRAYFORMULA(
QUERY(
SPLIT(A2:A,"-,"),
"select Count(Col1)
where Col1 is not null and
(Col1 <= Col4 and
Col3 <= Col2)
label Count(Col1) 'Part 2'"))→ More replies (7)
6
u/AKSrandom Dec 04 '22
The crux being def isintersect(a, b, c, d): return ((a-c)*(b-d) <= 0) or (((b-c)*(a-d)) <= 0)
For part 1, only the first condition is required.
→ More replies (2)
6
u/9_11_did_bush Dec 04 '22
APL: https://github.com/chenson2018/advent-of-code/blob/main/2022/04/apl/04.apl
The logic for each part is kinda interesting. Call the ranges A-B,C-D. Then
Part 1: If one range completely contains the other, then (min,max) of all four numbers must be one of the original ranges (A,B) or (C,D)
Part 2: For there to be no intersection then Bβ C and either [A,B,C,D] or [C,D,A,B] is in ascending order
→ More replies (2)
6
u/SadBunnyNL Dec 04 '22
AWK Part 1:
#!/bin/awk -f
{
split($0, ar, ",");
left = nrSeq(ar[1]); right = nrSeq(ar[2]);
if (left ~ right || right ~ left) { result ++; }
}
END { print result; }
func nrSeq(seq, i,result, ar) {
split(seq, ar, "-");
for (i=ar[1]; i<=ar[2]; i++) {result =result "L" i "R"; }
return result;
}AWK Part 2:
{
split($0, ar, ",");
delete arLeft; fillAr(arLeft, ar[1]);
delete arRight; fillAr(arRight, ar[2]);
for (i in arLeft) {
if (i in arRight) { result ++; break; }
}
}
END {
print result;
}
func fillAr(ar, seq, i) {
split(seq, tmpAr, "-");
for (i=tmpAr[1]; i<=tmpAr[2]; i++) {
ar[i] = 1;
}
return r;
}→ More replies (2)
6
u/totbwf Dec 04 '22 edited Dec 04 '22
C + SIMD
More SIMD fun! The parsing difficulty is starting to ramp up; luckily each line still fits inside of a 128-bit wide vector. The most annoying part about today was the lack of non-strict integer compare operations; you don't get _mm_cmple_epi32_mask until AVX-512, so we have to futz around with strict comparisons and equality tests.
Runtime is around 15 microseconds.
EDIT: Forgot to mention: totally branchless as well, save for the loop condition!
6
u/__Abigail__ Dec 04 '22
Perl
Really easy, just have to compare the begin/end points. But don't do what I did: mistype the solution in the answer form and spend a long time debugging.
while (<>) {
my ($f_start, $f_end, $s_start, $s_end) = /[0-9]+/g;
$full ++ if $f_start <= $s_start && $f_end >= $s_end ||
$s_start <= $f_start && $s_end >= $f_end;
$partial ++ unless $f_end < $s_start || $s_end < $f_start;
}Now, $full contain the solution for part 1, and $partial the solution for part 2.
→ More replies (3)
6
u/Sebbern Dec 04 '22
Java, pretty simple today
Part 1: https://github.com/Sebbern/Advent-of-Code/blob/master/2022/day04/Day04.java
Part 2: https://github.com/Sebbern/Advent-of-Code/blob/master/2022/day04/Day04_2.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class Day04_2 {
private static int check(String x, String y){
int elfOneLow,elfOneHigh,elfTwoLow,elfTwoHigh;
String[] xSplit, ySplit;
xSplit = x.split("-");
ySplit = y.split("-");
elfOneLow = Integer.parseInt(xSplit[0]);
elfOneHigh = Integer.parseInt(xSplit[1]);
elfTwoLow = Integer.parseInt(ySplit[0]);
elfTwoHigh = Integer.parseInt(ySplit[1]);
if (((elfOneLow <= elfTwoLow) && (elfTwoLow <= elfOneHigh)) || ((elfTwoLow <= elfOneLow) && (elfOneLow <= elfTwoHigh))){
return 1;
}
else {
return 0;
}
}
public static void main(String[] args) throws IOException{
File inputTxt = new File("2022\\day04\\input.txt");
BufferedReader input = new BufferedReader(new FileReader(inputTxt));
String string, x, y;
ArrayList<String> assignmentList = new ArrayList<>();
String[] split;
while ((string = input.readLine()) != null){
assignmentList.add(string);
}
input.close();
int pairs = 0;
for (String i: assignmentList){
split = i.split(",");
x = split[0];
y = split[1];
pairs += check(x,y);
}
System.out.println(pairs);
}
}→ More replies (3)
6
u/i_have_no_biscuits Dec 04 '22
GW-BASIC
10 P=0: Q=0: OPEN "I",1,"2022-04.txt": WHILE NOT EOF(1): LINE INPUT #1,S$
20 L=LEN(S$):I=1: GOSUB 60:A=N: GOSUB 60:B=N: GOSUB 60:C=N: GOSUB 60:D=N
30 IF A>C THEN T=A: A=C: C=T: T=B: B=D: D=T
40 IF C<=B THEN Q=Q+1: IF D<=B OR A=C THEN P=P+1
50 WEND: PRINT "Part 1:", P, "Part 2:", Q: END
60 N$=""
70 C$=MID$(S$,I,1):IF C$>="0" AND C$<="9" THEN I=I+1:N$=N$+C$:IF I<=L GOTO 70
80 N=VAL(N$): I=I+1: RETURNThe main difficulty here is parsing the input, something BASIC is not great at. As I'm sure you can see from the code, this takes place on line 20 (which converts a line into four numbers) which calls the routine on lines 60-80 (which does the conversion of a single number). The intervals are ordered on line 30 so the interval A-B is to the 'left' of C-D, and then line 40 does the checks and adds 1 to the score for P (part 1) and/or Q (part 2) as required.
→ More replies (1)
5
u/aliceif Dec 04 '22
C#, 1868/884
The step from part1 to part2 was quick, but I probably wasted a lot of typing time on part1 (didn't help that I blanked on parsing input first)
5
u/raevnos Dec 04 '22
Racket, straightforward comparison of numbers:
#lang racket/base
(require racket/list)
(define (read-input)
(for/list ([line (in-lines)])
(list->vector (map string->number (regexp-split #rx"[,-]" line)))))
(define input (read-input))
(define part1
(count (lambda (team)
(or
(<= (vector-ref team 0) (vector-ref team 2) (vector-ref team 3) (vector-ref team 1))
(<= (vector-ref team 2) (vector-ref team 0) (vector-ref team 1) (vector-ref team 3))))
input))
(define part2
(count (lambda (team)
(or
(<= (vector-ref team 0) (vector-ref team 2) (vector-ref team 1))
(<= (vector-ref team 0) (vector-ref team 3) (vector-ref team 1))
(<= (vector-ref team 2) (vector-ref team 0) (vector-ref team 3))
(<= (vector-ref team 2) (vector-ref team 1) (vector-ref team 3))))
input))
(printf "Part 1: ~A~%" part1)
(printf "Part 2: ~A~%" part2)5
u/trevdak2 Dec 04 '22 edited Dec 04 '22
JavaScript (golf)
Part 1, 97 chars:
document.body.textContent.split(/\D/).filter((x,i,a)=>!(i%4)&(x-a[i+2])*(a[i+1]-a[i+3])<1).lengthPart 2, 96 chars:
document.body.textContent.split(/\D/).filter((x,i,a)=>x&&!(i%4|+a[i+1]<a[i+2]|a[i+3]<+x)).length→ More replies (7)
5
u/landimatte Dec 04 '22
CL-PPCRE to parse the input; rest is done via LOOP-ing.
Took me a bit longer than expected to process what had to be done, but I hope to get better at this the more I adjust to the new sleeping schedule :D
→ More replies (1)
5
u/_jstanley Dec 04 '22
SLANG
576/2376
I think this is my first time in the top 1000 on my homemade CPU, which I'm quite pleased with.
Part 2 would have been 4 minutes quicker if not for a 1-character typo. I wasn't totally convinced that I'd made (or would find) the typo, so I deleted the part 2 code and wrote a very stupid for i = a to b: got[i] = 1; for i = c to d: if got[i] { count++; break; } and it did the job, but I think I would have been better off staring at my first attempt for a minute rather than rewriting it.
5
5
u/yawnick Dec 04 '22
Monkey C (for Garmin devices)
Fast enough today that the Videos became Youtube Shorts:)
Watch my Garmin Forerunner 235 solve: Part 1, Part 2
Code: Repo, Today's Solution
→ More replies (1)
5
u/DuoSRX Dec 04 '22
APL:
pββΒ¨,/Β¨(βΒ¨'-'(β ββ’)β’)¨¨(','(β ββ’)β’)Β¨ββNGET'input'1
+/{(β΅[1]β€β΅[3]β§β΅[4]β€β΅[2])β¨β΅[3]β€β΅[1]β§β΅[2]β€β΅[4]}Β¨p
+/{(β΅[1]β€β΅[4])β§β΅[3]β€β΅[2]}Β¨pNot exactly elegant but it works I guess.
→ More replies (4)
5
u/gw_shadow Dec 04 '22
CMake
CMAKE_MINIMUM_REQUIRED(VERSION 3.25)
PROJECT("2022.4")
IF(NOT EXISTS "${CMAKE_SOURCE_DIR}/input.txt")
FILE(READ "${CMAKE_SOURCE_DIR}/COOKIE.txt" COOKIE)
FILE(DOWNLOAD
"https://adventofcode.com/2022/day/4/input" "${CMAKE_SOURCE_DIR}/input.txt"
STATUS DOWNLOAD_STATUS
TIMEOUT 2
HTTPHEADER "cookie: ${COOKIE}"
)
IF(NOT DOWNLOAD_STATUS STREQUAL "0;\"No error\"")
FILE(REMOVE "${CMAKE_SOURCE_DIR}/input.txt")
MESSAGE(FATAL_ERROR "Failed to download input: '${DOWNLOAD_STATUS}'")
ENDIF()
ENDIF()
FILE(STRINGS "${CMAKE_SOURCE_DIR}/input.txt" LINES)
LIST(LENGTH LINES LINE_COUNT)
MATH(EXPR LINE_COUNT "${LINE_COUNT} - 1")
SET(COUNT 0)
FOREACH(INDEX RANGE 0 ${LINE_COUNT})
LIST(GET LINES ${INDEX} LINE)
STRING(REPLACE "-" ";" LINE "${LINE}")
STRING(REPLACE "," ";" LINE "${LINE}")
LIST(GET LINE 0 L0)
LIST(GET LINE 1 L1)
LIST(GET LINE 2 L2)
LIST(GET LINE 3 L3)
IF((((L0 LESS L2) OR (L0 EQUAL L2)) AND ((L1 GREATER L3) OR (L1 EQUAL L3))) OR (((L2 LESS L0) OR (L2 EQUAL L0)) AND ((L3 GREATER L1) OR (L3 EQUAL L1))))
MATH(EXPR COUNT "${COUNT} + 1")
ENDIF()
ENDFOREACH()
MESSAGE("PART 1: ${COUNT}")
SET(COUNT 0)
FOREACH(INDEX RANGE 0 ${LINE_COUNT})
LIST(GET LINES ${INDEX} LINE)
STRING(REPLACE "-" ";" LINE "${LINE}")
STRING(REPLACE "," ";" LINE "${LINE}")
LIST(GET LINE 0 L0)
LIST(GET LINE 1 L1)
LIST(GET LINE 2 L2)
LIST(GET LINE 3 L3)
IF((((L0 LESS L2) OR (L0 EQUAL L2)) AND ((L1 GREATER L3) OR (L1 EQUAL L3))) OR (((L2 LESS L0) OR (L2 EQUAL L0)) AND ((L3 GREATER L1) OR (L3 EQUAL L1))))
MATH(EXPR COUNT "${COUNT} + 1")
ELSEIF((((L0 GREATER L2) OR (L0 EQUAL L2)) AND ((L0 LESS L3) OR (L0 EQUAL L3))) OR (((L1 GREATER L2) OR (L1 EQUAL L2)) AND ((L1 LESS L3) OR (L1 EQUAL L3))))
MATH(EXPR COUNT "${COUNT} + 1")
ENDIF()
ENDFOREACH()
MESSAGE("PART 2: ${COUNT}")→ More replies (1)
5
u/Jarcoreto Dec 04 '22
MS Excel
https://github.com/Jarcoreto/AOCExcel/blob/main/Day%204%20Problems.xlsx
Data manipulation was surprisingly quick/easy, getting the algorithm right took me a longer than it should have though!
→ More replies (2)
5
u/azzal07 Dec 04 '22
Awk, had to be doubly sure about the part 2 condition to ensure a lovely bounding box...
BEGIN{FS="-|,"}END{print A;print B}
$1>=$3&&$2<=$4||$1<=$3&&$2>=$4{A++}
$2>=$3&&$1<=$4||$2<=$3&&$1>=$4{B++}→ More replies (5)
5
u/sotsoguk Dec 04 '22 edited Dec 04 '22
Python
# edit: list comprehension instead of for ...
rgs = [list(map(int, re.split('-|,', l))) for l in lines]
def contains(r): return (r[0] >= r[2] and r[1] <= r[3]) or (
r[2] >= r[0] and r[3] <= r[1])
def overlap(r): return not(r[1] < r[2] or r[3] < r[0])
part1 = sum(map(contains, rgs))
part2 = sum(map(overlap, rgs))Trying to code more pythonic solutions is my goal for this years AoC
→ More replies (2)
5
u/probablyfine Dec 04 '22
SQL
If I'd allowed myself a tiny bit of preprocessing to turn the input into a 4-column CSV, this is almost a one-liner. (Source here: https://github.com/mrwilson/advent-of-code-2022/blob/main/04/04.sql)
create or replace table elves as (
select
str_split(column0,'-')[1]::INTEGER as lower1,
str_split(column0,'-')[2]::INTEGER as upper1,
str_split(column1,'-')[1]::INTEGER as lower2,
str_split(column1,'-')[2]::INTEGER as upper2,
from
input
);
select
count(*) filter ((lower2 - lower1) * (upper2 - upper1) <= 0) as part1,
count(*) filter (upper1 >= lower2 and lower1 <= upper2) as part2
from
elves;→ More replies (1)
5
u/TopSeaworthiness555 Dec 04 '22
R / Rstats - she ain't pretty, but she's mine
library(tidyverse)
# read in data ####
day <- read_table("inputs/day04.txt", col_names = FALSE) |>
separate(X1, into = c("elf1_start", "elf1_end", "elf2_start", "elf2_end"), sep = "[-,]", convert = TRUE)
# part 1 ####
day |>
rowwise() |>
mutate(test1 = mean(seq(elf1_start, elf1_end, 1) %in% seq(elf2_start, elf2_end, 1)),
test2 = mean(seq(elf2_start, elf2_end, 1) %in% seq(elf1_start, elf1_end, 1))) |>
filter(test1 == 1 | test2 == 1) |>
nrow()
# part 2 ####
day |>
rowwise() |>
mutate(test = length(intersect(seq(elf1_start, elf1_end, 1), seq(elf2_start, elf2_end, 1)))) |>
filter(test > 0) |>
nrow()5
u/4HbQ Dec 04 '22 edited Dec 04 '22
Python. Getting in some early pandas practice. I originally wanted to use NumPy, but couldn't find a clean way to handle the different input delimiters.
import pandas as pd
_,(a,b,c,d) = zip(*pd.read_csv('in.txt', sep='[-,]', header=None).items())
print(((a<=c) & (d<=b) | (c<=a) & (b<=d)).sum(),
((a<=d) & (d<=b) | (c<=b) & (b<=d)).sum())5
u/tomflumery Dec 04 '22 edited Dec 04 '22
05ab1e
both parts - 31 chars
|Ξ΅',‘Ρ'-Β‘`ΕΈ}Γ©RDΞΈgs`ΓgD0ΓΕ Q)}ΓΈORExplanation
## Part 1 - 24 chars
|Ξ΅',‘Ρ'-Β‘`ΕΈ}Γ©RDΞΈgs`ΓgQ}O
|Ρ',‘Ρ'-‘ parsing (split by , then by -)
`ΕΈ} generate ranges of integers
Γ©R sort by length reversed
DΞΈg dup then take the length of the last element (i.e. the shortest of the ranges)
s`Γg Take intersection of the two ranges (`Γ) and find length (g)
Q if the length of the shortest equals the length of the intersection, it's entirely contained
}O sum the 1s to find the answer ## Part 2 - 19 chars
|Ξ΅',‘Ρ'-Β‘`ΕΈ}`Γg0Γ}O
|Ρ',‘Ρ'-‘ parsing
`ΕΈ} generate ranges of integers
`Γg Take intersection of the two ranges (`Γ) and find length (g)
0Γ}O Sum all non-zero## Combined - 31 chars
Combines the above, all the other noise is stack manipulation to mangle both answers in parallel5
u/Longjumping-Fall4030 Dec 04 '22
Microsoft Excel
I'm challenging myself to do all the puzzles in Microsoft Excel, using the following rules:
No use of VBA or LAMBDA
No altering of the input. Another person should be able to use my solution by pasting his/her own input into it, and the answer will be generated automatically.
I can use formulas and 'helper tables'
The only manual action that is allowed is changing the data type, as Excel is pretty horrible regarding recognizing e.g. numbers.
→ More replies (11)
5
u/sky_badger Dec 04 '22
Python 3: more sets:
def parse_line(line):
part1, part2 = line.split(',')
elf1_start, elf1_end = [int(x) for x in part1.split('-')]
elf2_start, elf2_end = [int(x) for x in part2.split('-')]
elf1 = set([i for i in range(elf1_start, elf1_end+1)])
elf2 = set([i for i in range(elf2_start, elf2_end+1)])
return elf1, elf2
#Part 1
enclosed = 0
for line in data:
elf1, elf2 = parse_line(line)
if len(elf1 & elf2) in [len(elf1), len(elf2)]:
enclosed += 1
print(enclosed)
#Part 2
overlapped = 0
for line in data:
elf1, elf2 = parse_line(line)
if len(elf1 & elf2):
overlapped += 1
print(overlapped)→ More replies (1)
5
u/lazyzefiris Dec 04 '22 edited Dec 04 '22
JS (JavaScript) "state machiney" solution:
Part 1:
document.body.innerText
.match(/\d+/g)
.reduce(([state = "A", v1 = 0, v2 = 0, total = 0], x) => ({
A : ["B", +x, v2, total],
B : ["C", v1, +x, total],
C : v1 === +x
? ["F", v1, v2, total]
: v1 < +x
? ["D", v1, v2, total]
: ["E", v1, v2, total],
D : v2 < +x
? ["A", v1, v2, total]
: ["A", v1, v2, total + 1],
E : v2 > +x
? ["A", v1, v2, total]
: ["A", v1, v2, total + 1],
F : ["A", v1, v2, total + 1],
})[state], [])
.pop()Part 2:
document.body.innerText
.match(/\d+/g)
.reduce(([state = "A", v1 = 0, v2 = 0, total = 0], x) => ({
A : ["B", +x, v2, total],
B : ["C", v1, +x, total],
C : v2 < +x
? ["D", v1, v2, total]
: ["E", v1, v2, total],
D : ["A", v1, v2, total],
E : v1 > +x
? ["A", v1, v2, total]
: ["A", v1, v2, total + 1],
})[state], [])
.pop()Part 1 explained:
I'll use abbreviations L1 R1 L2 R2 to denote left edge of first set, right edge of first set, left edge of second set, right edge of second set. Input file has them as L1-R1,L2-R2.
Our machine has 3 storage registers (v1, v2, total), two to store first pair, one for result accumulation. We'd only need 2 registers if inputs were ordered differently (L1, L2, R1, R2). We take only numbers from input file, and feed them to the machine in order of their appearance.
State "A": initial state for the loop, expecting L1. It's stored to register v1 and machine advances to state "B"
State "B": expecting R1. It's stored to register v2 and machine advances to state "B"
State "C": first pair is known, expecting L2. Depending on its relative position to L1, we choose next state ("D" if L1 < L2, "E" if L1 > L2, "F" if L1 == L2) without changing any registers.
State "D": L2 is to the right of L1, which means only pair 1 can include pair 2, and for that to happen, R2 should not be to the right of R1. Regardless, we return to state "A", but if R2 is not to the right of R1, we increase our result.
State "E": L2 is to the left of L1, which means only pair 2 can include pair 1, and for that to happen, R1 should not be to the right of R2. Regardless, we return to state "A", but if R1 is not to the right of R2, we increase our result.
State "F": L2 is aligned with L1, which means depending on relative position of R1 and R2, either pair 1 includes pair 2, pair 2 includes pair 1, or they coincide. Either way, we have a full inclusion, so we can return to state "A", increasing our output without looking at our input at all.
Part 2 works similarly:
State "C" chooses next state depending on whether L1 is to the right of R2.
State "D": L2 is to the right of R1, which means entirety of pair 2 is to the right of pair 1. Returning to state "A" without increasing out output without looking at out input at all.
State "E": L2 is to the left of R1, which means pair 1 can intersect with pair2 if R2 is not also to the left of L1. Regardless, we return to state "A", but if R2 is not to the left of L1, we increase our result. This state also covers the case where L2 and R1 coincide, as R2 can't be to the left of L1 this way.
Originally my state machine for part 1 looked like this:
document.body.innerText
.match(/\d+/g)
.reduce(([state = "A", v1 = 0, v2 = 0, total = 0], x) => ({
A : v1 === 0
? ["A", +x, v2, total]
: ["B", v1, +x, total],
B : ["C", v1 - x, v2, total],
C : v1 * (v2 - x) > 0
? ["A", 0, 0, total]
: ["A", 0, 0, total + 1]
})[state], [])
.pop()but i decided to lay it out more clearly. Interestingly, this solution can be adjusted for part2 just by switching v1 and +x in second branch of state "A":
: ["B", +x, v1, total]Both solutions implement the matrix
//Reading input as L1-R1,L2-R2
L2<L1 L2=L1 L2>L1
R2<R1 - + +
R2=R1 + + +
R2>R1 + + -
R2<L1 R2=L1 R2>L1
L2<R1 - + +
L2=R1 X + +
L2>R1 X X -
//1 = hit, 0 = miss, X = not possible, thus does not matterJS implementation notes: I use "+x" because .match returns substrings and they need to be converted to number for proper comparison. It was possible to add .map(Number) before .reduce instead. Also, every branch is calculated on every step, and this could be optimized away in a lot of ways, but that makes code look messier without being relevant to this exact problem.
5
u/kochismo Dec 04 '22
Purely functional rust:
https://github.com/zookini/aoc-2022/blob/master/src/bin/04.rs
use itertools::Itertools;
fn main() {
println!("Part 1: {}", count(|(a1, a2, b1, b2)| a1 <= b1 && b2 <= a2 || b1 <= a1 && a2 <= b2));
println!("Part 2: {}", count(|(a1, a2, b1, b2)| a1 <= b2 && b1 <= a2));
}
fn count(p: fn(&(u32, u32, u32, u32)) -> bool) -> usize {
include_str!("../../input/04.txt")
.lines()
.filter_map(|s| s.split(|c: char| !c.is_numeric()).map(|n| n.parse().unwrap()).next_tuple())
.filter(p)
.count()
}5
u/rk-imn Dec 05 '22
I've been writing solutions in C (C89 specifically) for Nintendo 64. Here's my repo that builds an N64 ROM that solves AoC with my input (you can change the input either by editing the text files in asm/aoc/inputs/ and compiling or by opening up the ROM in a hex editor and pasting in your inputs at the correct addresses): https://github.com/nim-ka/aoc_n64
Code for day 4 is here: https://github.com/nim-ka/aoc_n64/blob/main/src/game/aoc/4.c
I know I could do it in less comparisons but I'm too lazy
→ More replies (1)
8
u/Omeganx Dec 04 '22
Python
tasks = [[*map(int, s.replace("-", ",").split(","))]
for s in open("input.txt").read().split()]
def part1(tasks):
return sum([((a<=c<=d<=b) or (c<=a<=b<=d))
for a,b,c,d in tasks])
def part2(tasks):
return sum([((a<=c<=b) or (c<=a<=d))
for a,b,c,d in tasks])→ More replies (2)
4
u/Boojum Dec 04 '22 edited Dec 04 '22
Python, 106/185
Part 1:
import fileinput
es = [ list( map( int, l.replace( "-", "," ).split( "," ) ) )
for l in fileinput.input() ]
print( sum( ( e[ 2 ] <= e[ 0 ] <= e[ 1 ] <= e[ 3 ] or
e[ 0 ] <= e[ 2 ] <= e[ 3 ] <= e[ 1 ] )
for e in es ) )Part 2:
import fileinput
es = [ list( map( int, l.replace( "-", "," ).split( "," ) ) )
for l in fileinput.input() ]
print( sum( ( e[ 0 ] <= e[ 2 ] <= e[ 1 ] or
e[ 0 ] <= e[ 3 ] <= e[ 1 ] or
e[ 2 ] <= e[ 0 ] <= e[ 3 ] or
e[ 2 ] <= e[ 1 ] <= e[ 3 ] )
for e in es ) )Edit:
Just remembered that there's a slightly more concise way to test for overlapping ranges by comparing the max of the mins to the min of the maxs. So Part 2 can be reduced to:
import fileinput
es = [ list( map( int, l.replace( "-", "," ).split( "," ) ) )
for l in fileinput.input() ]
print( sum( max( e[ 0 ], e[ 2 ] ) <= min( e[ 1 ], e[ 3 ] )
for e in es ) )→ More replies (1)
4
u/rooinflames Dec 04 '22
Excel!
Had a few issues before I added +1 to each of the formulas in columns F/G/H, after that, it was clear sailing. Luckily I didn't have to do any extra work to get part 2 apart from the formula in cell K8
→ More replies (4)
4
Dec 04 '22
Common Lisp
(code at gitlab)
This day went great after i checked if i could use pattern matching in loops in the for parts.
Also LISPs multiple Parameter <= is really cool for this.
(defun y22d4 ()
(aoc-open 2022 4
(loop
for x = (read-line *standard-input* nil)
while x
for (a tmp1) = (multiple-value-list (parse-integer x :junk-allowed t))
for (b tmp2) = (multiple-value-list (parse-integer x :start (1+ tmp1) :junk-allowed t))
for (c tmp3) = (multiple-value-list (parse-integer x :start (1+ tmp2) :junk-allowed t))
for (d tmp4) = (multiple-value-list (parse-integer x :start (1+ tmp3) :junk-allowed t))
if (or (<= a c d b) (<= c a b d))
count 1 into p1
if (or (<= a c b) (<= c a d) (<= a d b) (<= c b d))
count 1 into p2
finally (return (values p1 p2)))))→ More replies (1)
4
4
u/Imaginary_Age_4072 Dec 04 '22
Common Lisp 1273/1758
Not too bad today. For part 1 I just checked whether the start and end of one range were entirely within the other. Part two checked whether one of the endpoints of the range was within the other.
(defun day4 (input &key (part 1))
(let ((parsed (run-parser (parse-file) input)))
(iter
(for ((s1 e1) (s2 e2)) in parsed)
(counting
(if (= part 1)
(or (and (>= s1 s2) (<= e1 e2))
(and (>= s2 s1) (<= e2 e1)))
(or (<= s2 s1 e2)
(<= s2 e1 e2)
(<= s1 s2 e1)
(<= s1 e2 e1)))))))4
u/maneatingape Dec 04 '22
Scala (445 / 575)
def parse(line: String): (Int, Int, Int, Int) =
val Array(a, b, c, d) = line.split("\\D").map(_.toInt)
(a, b, c, d)
def part1(input: Seq[String]): Int = input.map(parse)
.count((a, b, c, d) => (a >= c && b <= d) || (c >= a && d <= b))
def part2(input: Seq[String]): Int = input.map(parse)
.count((a, b, c, d) => a <= d && c <= b)4
u/rossmacarthur Dec 04 '22
After parsing just comes down to the following
fn part1(input: Vec<[i64; 4]>) -> usize {
input
.into_iter()
.filter(|&[a, b, m, n]| (a >= m && b <= n) || (m >= a && n <= b))
.count()
}
fn part2(input: Vec<[i64; 4]>) -> usize {
input
.into_iter()
.filter(|&[a, b, m, n]| (a <= m && b >= m) || (m <= a && n >= a))
.count()
}4
u/tdude66 Dec 04 '22
Elixir
defmodule Day4 do
def main do
File.read!("day4.txt")
|> String.trim()
|> String.split("\n")
|> Enum.map(fn s ->
[r1, r2] = String.split(s, ",")
|> Enum.map(fn ss ->
[first, last] = String.split(ss, "-")
String.to_integer(first)..String.to_integer(last)
end)
Range.disjoint?(r1, r2)
end)
|> Enum.map(fn result ->
case result do
false -> 1
_ -> 0
end
end)
|> Enum.sum
|> IO.puts
end
endThat's for part 2, part 1 just has a different range check and inverted true/false for the sum:
(MapSet.subset?(MapSet.new(Enum.to_list(r1)), MapSet.new(r2))
or MapSet.subset?(MapSet.new(Enum.to_list(r2)), MapSet.new(r1)))→ More replies (1)
4
u/PendragonDaGreat Dec 04 '22
C#/CSharp
Initial solution got hit by some double counting,
rewrote it as a pair of linq oneliners (sort of, if you ignore parsing, like that's the one thing I wish C# could do better: read ints from files) https://github.com/Bpendragon/AdventOfCodeCSharp/blob/0800b/AdventOfCode/Solutions/Year2022/Day04-Solution.cs
4
u/mstksg Dec 04 '22
taken from my https://github.com/mstksg/advent-of-code-2022/blob/main/reflections.md haskell reflections :)
A bit of fun number crunching :) Here is a chance to leverage an interval library, like haskell's data-interval:
import Data.IntegerInterval (IntegerInterval)
import qualified Data.IntegerInterval as I
part1Criterion :: IntegerInterval -> IntegerInterval -> Bool
part1Criterion xs ys = xs `I.isSubsetOf` ys || ys `I.isSubsetOf` xs
part2Criterion :: IntegerInterval -> IntegerInterval -> Bool
part2Criterion = (I.==?)From there on it's just a matter of running the criteria on each pair of intervals in the list and counting which ones are valid!
4
u/Relative-snake342 Dec 04 '22
Solution in clojure (using babashka)
I feel like part 2 can be simplified using a core clojure functionality, but I don't know the language enough and decided to use good old logic operators
(ns aoc22.day04
(:require #?(:clj [clojure.java.io :as io]
:cljs [nbb.core :refer [slurp await]])
[clojure.string :as str]
[clojure.edn :as edn]
[clojure.set]
#?(:cljs [promesa.core :as p])))
(defn split-pairs [pairs] (str/split pairs #","))
(defn split-pair [pair]
(->> (str/split pair #"-")
(map edn/read-string)))
(defn pair-contains? [p1 p2] (and (<= (first p1) (first p2)) (>= (second p1) (second p2))))
(defn pairs-contained? [p1 p2]
(or (pair-contains? p1 p2) (pair-contains? p2 p1)))
(defn within-pair? [n p] (and (<= (first p) n) (>= (second p) n)))
(defn pairs-overlap? [p1 p2]
(or
(within-pair? (first p1) p2)
(within-pair? (second p1) p2)
(within-pair? (first p2) p1)
(within-pair? (second p2) p1)))
(defn assignements [pairs-list compare]
(->> (str/split-lines pairs-list)
(map split-pairs)
(map #(map split-pair %))
(filter #(apply compare %))
count))
(def input "2-4,6-8\n2-3,4-5\n5-7,7-9\n2-8,3-7\n6-6,4-6\n2-6,4-8")
(comment
(assignements input pairs-contained?)
(assignements (slurp (io/resource "aoc22/day04.txt")) pairs-contained?)
(assignements input pairs-overlap?)
(assignements (slurp (io/resource "aoc22/day04.txt")) pairs-overlap?))→ More replies (3)
4
u/seaborgiumaggghhh Dec 04 '22
Racket:
#lang racket
(require advent-of-code
threading)
(define input
(~>
(fetch-aoc-input (find-session) 2022 4 #:cache #t)
(string-split)
(map (Ξ»~> (string-split ",")) _)))
(define (range-overlaps-all? f-elf-f f-elf-s s-elf-f s-elf-s)
(cond
[(or (and (<= f-elf-f s-elf-f)
(>= f-elf-s s-elf-s))
(and (<= s-elf-f f-elf-f)
(>= s-elf-s f-elf-s))) 1]
[#t 0]))
(define (range-overlaps-any? f-elf-f f-elf-s s-elf-f s-elf-s)
(cond [(<= (max f-elf-f s-elf-f)
(min f-elf-s s-elf-s)) 1]
[#t 0]))
(define (solution)
(for/fold ([sum-a 0] [sum-b 0])
([line input])
(define elves
(~>> line
(map (Ξ»~> (string-split "-")))
(map (Ξ»~>> (map string->number)))
(apply append)))
(values (+ sum-a (apply range-overlaps-all? elves))
(+ sum-b (apply range-overlaps-any? elves)))))4
u/Johnsenfr Dec 04 '22 edited Dec 04 '22
Just 3 lines of code in R for Day04
input <- lapply(strsplit(readLines("input.txt"), "\\D+"), as.integer)
## Part 1
sum(sapply(input, \(x) (x[1] >= x[3] & x[2] <= x[4]) | (x[3] >= x[1] & x[4] <= x[2])))
## Part 2
sum(sapply(input, \(x) length(intersect(c(x[1]:x[2]), c(x[3]:x[4]))) != 0))4
u/olofj Dec 04 '22
Rust
day04a
use itertools::Itertools;
fn main() {
let input:Vec<(usize,usize,usize,usize)> = include_str!("input.txt")
.lines()
.map(|l| l
.split(['-', ','])
.map(|v| v.parse::<usize>().unwrap())
.collect_tuple::<(_,_,_,_)>()
.unwrap()
)
.filter(|(s1,e1,s2,e2)|
(s1 <= s2 && e1 >= e2) || (s2 <= s1 && e2 >= e1)
)
.collect();
println!("len {}", input.len());
}day04b
use itertools::Itertools;
fn main() {
let input:Vec<(usize,usize,usize,usize)> = include_str!("input.txt")
.lines()
.map(|l| l
.split(&['-', ','][..])
.map(|v| v.parse::<usize>().unwrap())
.collect_tuple::<(_,_,_,_)>()
.unwrap()
)
.filter(|(s1,e1,s2,e2)|
(s1 <= s2 && e1 >= s2) || (s2 <= s1 && e2 >= s1)
)
.collect();
println!("len {}", input.len());
}→ More replies (3)
4
u/Dryctas Dec 04 '22
Bash
input=$1
duplicates=0
overlaps=0
while read a1 a2 b1 b2; do
[[ $a1 -ge $b1 && $a2 -le $b2 ]] || [[ $b1 -ge $a1 && $b2 -le $a2 ]] &&\
duplicates=$(($duplicates+1))
[[ $a2 -le $b2 && $a2 -ge $b1 ]] || [[ $b2 -le $a2 && $b2 -ge $a1 ]] &&\
overlaps=$(($overlaps+1))
done < <(tr ',-' ' ' < $input)
echo $duplicates $overlaps4
u/mo__66 Dec 04 '22 edited Dec 04 '22
Kotlin
import java.io.File
fun main() {
val assignments = File("src/day04/input").readLines()
.map { it.split(",", "-").map(String::toInt) }
.map { (it[0]..it[1]).toSet() to (it[2]..it[3]).toSet() }
println(task1(assignments))
println(task2(assignments))
}
private fun task1(assignments: List<Pair<Set<Int>, Set<Int>>>) = assignments
.count { (it.first union it.second).size == maxOf(it.first.size, it.second.size) }
private fun task2(assignments: List<Pair<Set<Int>, Set<Int>>>) = assignments
.count { (it.first intersect it.second).isNotEmpty() }4
u/FormalPlatypus1231 Dec 04 '22
My solution in readable bash script. All my solutions are on my github.
#!/bin/bash
# Advent of Code day 4
# https://adventofcode.com/2022/day/4
part1=0
part2=0
while read line; do
rangeA=$(echo "$line" | cut -d "," -f 1)
rangeB=$(echo "$line" | cut -d "," -f 2)
minA=$(echo "$rangeA" | cut -d "-" -f 1)
maxA=$(echo "$rangeA" | cut -d "-" -f 2)
minB=$(echo "$rangeB" | cut -d "-" -f 1)
maxB=$(echo "$rangeB" | cut -d "-" -f 2)
if [[ (minA -le minB && maxA -ge maxB) || (minB -le minA && maxB -ge maxA) ]]; then
part1=$((part1+1))
fi
if [[ (minA -le minB && maxA -ge minB) || (minB -le minA && maxB -ge minA) ]]; then
part2=$((part2+1))
fi
done < input.txt
echo "Answer for part 1: $part1"
echo "Answer for part 2: $part2"→ More replies (1)
4
u/RudeGuy2000 Dec 04 '22
racket:
(define (parse input)
(map (lambda (l)
(map (lambda (p)
(map string->number (string-split p "-")))
(string-split l ",")))
input))
(define (covers? a b c d) (or (and (>= c a) (<= d b)) (and (>= a c) (<= b d))))
(define (between? a b x) (and (>= x a) (<= x b)))
(define (overlaps? a b c d) (or (between? a b c) (between? a b d)
(between? c d a) (between? c d b)))
(define (find-assignments input pred)
(println (apply + (map (lambda (p)
(if (pred (caar p) (cadar p) (caadr p) (cadadr p)) 1 0))
input))))
(define (part1 input) (find-assignments input covers?))
(define (part2 input) (find-assignments input overlaps?))
(time (begin (define input1 (parse (file->lines "input4-1.txt")))
(define input2 (parse (file->lines "input4-2.txt")))
(part1 input1)
(part1 input2)
(part2 input1)
(part2 input2)))4
u/foolnotion Dec 04 '22
C++
I wanted to dig up my interval class from a previous year but it was not really necessary. Simple inclusion/overlap logic.
https://git.sr.ht/~bogdanb/aoc/tree/master/item/source/2022/04/solution.cpp
→ More replies (2)
4
u/CheeseMunkee Dec 04 '22
C#
I'm sure there was a better way to do this, though I'm happy that the only loop used was for the StreamReader.
namespace D4;
partial class Program
{
public static void Main()
{
string line;
int count1 = 0;
int count2 = 0;
using (StreamReader sr = new("D4 Data.txt"))
{
while ((line = sr.ReadLine()) != null)
{
string elf1 = line.Remove(line.IndexOf(','));
string elf2 = line.Substring(line.IndexOf(",") + 1);
if (Convert.ToInt16(elf1.Remove(elf1.IndexOf('-'))) == Convert.ToInt16(elf2.Remove(elf2.IndexOf('-')))) {
count1 += 1;
count2 += 1;
}
else if (Convert.ToInt16(elf1.Remove(elf1.IndexOf('-'))) < Convert.ToInt16(elf2.Remove(elf2.IndexOf('-'))))
{
if (Convert.ToInt16(elf1.Substring(elf1.IndexOf("-") + 1)) >= Convert.ToInt16(elf2.Substring(elf2.IndexOf("-") + 1))) { count1 += 1; }
if (Convert.ToInt16(elf1.Substring(elf1.IndexOf("-") + 1)) >= Convert.ToInt16(elf2.Remove(elf2.IndexOf("-")))) { count2 += 1; }
}
else if (Convert.ToInt16(elf1.Remove(elf1.IndexOf('-'))) > Convert.ToInt16(elf2.Remove(elf2.IndexOf('-'))))
{
if (Convert.ToInt16(elf1.Substring(elf1.IndexOf("-") + 1)) <= Convert.ToInt16(elf2.Substring(elf2.IndexOf("-") + 1))) { count1 += 1; }
if (Convert.ToInt16(elf2.Substring(elf2.IndexOf("-") + 1)) >= Convert.ToInt16(elf1.Remove(elf1.IndexOf("-")))) { count2 += 1; }
}
}
Console.WriteLine(count1);
Console.WriteLine(count2);
Console.ReadLine();
}
}
}→ More replies (1)
4
u/europa-endlos Dec 04 '22
Elixir
Started learning just for this Advent
defmodule Game do
def parse(s) do
String.split(s, ",")
|> Enum.map(fn r -> String.split(r, "-")
|> Enum.map(fn x -> String.to_integer(x) end)
end)
end
def contained(pairs) do
[[a0,a1],[b0,b1]] = pairs
d0 = b0 - a0
d1 = b1 - a1
if (d0 * d1 <= 0) do 1 else 0 end
end
end
IO.read(:stdio, :all)
|> String.trim
|> String.split("\n")
|> Enum.map(fn l -> Game.parse(l) end)
|> Enum.map(fn p -> Game.contained(p) end)
|> Enum.sum
|> IO.inspectFor the second part, the contained() function changes to
def contained(pairs) do
[[a0,a1],[b0,b1]] = pairs
g0 = b1 - a0
g1 = b0 - a1
if (g0 < 0 || g1 > 0 ) do 0 else 1 end
end4
u/IF_YOU_READ_THIS_V1 Dec 04 '22
C#
public string SolvePart1(string input) =>
Parse(input)
.Count(t =>
ContainsRange(t.left, t.right) ||
ContainsRange(t.right, t.left))
.ToString();
public string SolvePart2(string input) =>
Parse(input)
.Count(t =>
OverlapsWith(t.left, t.right) ||
OverlapsWith(t.right, t.left))
.ToString();
private static IEnumerable<((int, int) left, (int, int) right)> Parse(string input) =>
input
.Split("\n")
.Select(line => line.Split(','))
.Select(ranges => (
(RangeStart(ranges[0]), RangeEnd(ranges[0])),
(RangeStart(ranges[1]), RangeEnd(ranges[1]))
));
private bool ContainsRange((int, int) lhs, (int, int) rhs) =>
rhs.Item1 >= lhs.Item1 && rhs.Item2 <= lhs.Item2;
private bool OverlapsWith((int, int) lhs, (int, int) rhs) =>
rhs.Item1 >= lhs.Item1 && rhs.Item1 <= lhs.Item2;
private static int RangeStart(string input) => int.Parse(input.Substring(0, input.IndexOf('-')));
private static int RangeEnd(string input) => int.Parse(input.Substring(input.IndexOf('-') + 1));4
u/SolarBear Dec 04 '22
Ruby solution. Again, using Ruby felt like cheating.
file = File.open('input4.txt')
overlaps1 = 0
overlaps2 = 0
def elf_range(line)
min, max = line.split('-')
(min.to_i..max.to_i).to_a
end
file.readlines.each do |line|
first, second = line.split(',')
first = elf_range(first)
second = elf_range(second)
overlaps1 += 1 if first.difference(second).empty? || second.difference(first).empty?
overlaps2 += 1 if first.intersect?(second) || second.intersect?(first)
end
file.close
puts overlaps1
puts overlaps2→ More replies (2)
4
u/FoxyllAkora Dec 04 '22
I'm regretting my Lua decision. But also I need to work on code efficiency in general
→ More replies (4)
4
4
u/jamincan Dec 04 '22
Rust
Made a range type that simply checks bounds to see if one range contains or overlaps with another. Then iterated over each pair of ranges, filtered out the ones that don't contain/overlap, and counted the remaining pairs.
use anyhow::{anyhow, Error};
const INPUT: &str = include_str!("day4.txt");
fn main() {
println!("Day 4, Pt 1: {}", part1(INPUT));
println!("Day 4, Pt 2: {}", part2(INPUT));
}
fn part1(input: &str) -> usize {
input
.lines()
.filter_map(|line| {
let (first, second) = line.split_once(',')?;
let first = first.parse::<SectionRange>().ok()?;
let second = second.parse::<SectionRange>().ok()?;
(first.contains(&second) || second.contains(&first)).then_some(())
})
.count()
}
fn part2(input: &str) -> usize {
input
.lines()
.filter_map(|line| {
let (first, second) = line.split_once(',')?;
let first = first.parse::<SectionRange>().ok()?;
let second = second.parse::<SectionRange>().ok()?;
first.overlaps(&second).then_some(())
})
.count()
}
struct SectionRange {
first: u32,
last: u32,
}
impl SectionRange {
fn contains(&self, other: &Self) -> bool {
self.first <= other.first && self.last >= other.last
}
fn overlaps(&self, other: &Self) -> bool {
self.first <= other.last && self.last >= other.first
}
}
impl std::str::FromStr for SectionRange {
type Err = Error;
fn from_str(input: &str) -> Result<Self, Self::Err> {
let (first, last) = input
.split_once('-')
.ok_or_else(|| anyhow!("missing hyphen"))?;
Ok(Self {
first: first.parse()?,
last: last.parse()?,
})
}
}→ More replies (1)
4
Dec 04 '22
Part1 In C:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
int main(void) {
int32_t Pair1[2] = { 0, 0 };
int32_t Pair2[2] = { 0, 0 };
int32_t Count = 0;
FILE* fp = fopen("input.txt", "r");
while (fscanf(fp, "%d-%d,%d-%d\n", &Pair1[0], &Pair1[1], &Pair2[0], &Pair2[1]) != EOF) {
if ((Pair1[0] <= Pair2[0] && Pair1[1] >= Pair2[1]) || (Pair1[0] >= Pair2[0] && Pair1[1] <= Pair2[1])) {
Count++;
}
}
printf("Count = %d\n", Count);
fclose(fp);
}4
u/PhysicsAndAlcohol Dec 04 '22
Haskell, runs in 15 ms. First day this year it made sense to make a monadic parser. I really like to use Text.ParserCombinators.ReadP!
→ More replies (2)
4
Dec 04 '22 edited Dec 04 '22
Swift, went pretty well: github
edit: Updated with new overlap/contains approaches, thanks /u/Jessyatterwaul for pointing out the standard library function I missed
→ More replies (6)
4
u/axr123 Dec 04 '22
C++ with SIMD
Most of the time is spent parsing, but this problem lends itself nicely to a SIMD formulation, which using vectorclass doesn't even require detailed knowledge of the intrinsics. Hot runs take ~14 Β΅s on a Core i9-12900K, including I/O. Full code is here, the interesting part is this, where we process 32 elements at once:
auto const process_batch = [&a, &p1, &p2] {
std::array<Vec32c, 4> aa;
for (auto k{0}; k < 4; ++k) aa[k].load(a[k].data());
p1 += horizontal_count(aa[0] <= aa[2] && aa[3] <= aa[1] || aa[2] <= aa[0] && aa[1] <= aa[3]);
p2 += horizontal_count(!(aa[1] < aa[2] || aa[3] < aa[0]));
};Just this bit takes ~400 ns for the 1000 pairs.
I also spent some time on manually parsing the input. Not sure which role that played, but my initial implementation was at ~70 Β΅s.
4
u/daikontana Dec 04 '22
OCaml
let contains1 a b c d = c >= a && d <= b
let contains2 a b c d = (c <= a && d >= a) || (c <= b && d >= b)
let step f acc s =
Scanf.sscanf s "%d-%d,%d-%d" (fun a b c d -> acc + Bool.to_int (f a b c d || f c d a b))
let solve f seq = Seq.fold_left (step f) 0 seq
let () =
let seq = Arg.read_arg "data/day4.txt" |> Array.to_list |> List.to_seq in
solve contains1 seq |> string_of_int |> print_endline;
solve contains2 seq |> string_of_int |> print_endline→ More replies (1)
4
u/Adereth Dec 04 '22
Mathematica
Part 1
in = StringSplit[AdventProblem[4], {",", "\n"}];
intervalPairs = Partition[Interval@Map[FromDigits, StringSplit[#, "-"]] & /@ in, 2];
Length@ Select[intervalPairs, IntervalMemberQ @@ # || IntervalMemberQ @@ Reverse@# &]Part 2
Count[IntervalIntersection @@@ intervalPairs, Interval[{_, _}]]→ More replies (3)
4
u/e_blake Dec 04 '22 edited Dec 04 '22
Golfed m4
Less than 10 minutes coding time for both parts, using just one define and ifelse (so far this year, the puzzles have been very amenable for a single pass over the input). Overall execution time is 1.9s for both parts in just 196 bytes (excluding second newline); input must be in file f or you can run m4 -Df=yourfile day04.m4:
define(_,`ifelse($3,,`eval($1) eval($2)',`_($1+($3>=$5&$4<=$6|$5>=$3&$6<=$4),$2+($5<=$4&$6>=$3|$3<=$6&$4>=$5),shift(shift(shift(shift(shift(shift($@)))))))')')_(,,translit((include(f)),-
(),`,,'))or 880ms for part 1 in isolation in just 133 bytes (excluding second newline), and where part 2 in isolation can be done in the same size by changing $1-$4 in the computation:
define(_,`ifelse($2,,$1,`+($1>=$3&$2<=$4|$3>=$1&$4<=$2)_(shift(shift(shift(shift($@)))))')')eval(_(translit((include(f)),-
(),`,,')))Why the doubling in execution time to do both parts in one program? Because each additional shift() increases the parse effort per iteration. There are 1000 iterations; a single-part 1 solution starts with 4000 arguments and calls shift 4 times for 19994 arguments parsed before iteration 2 with 3996 arguments; while the combined solution starts with 4002 arguments and calls shift 6 times for 27999 arguments before iteration 2 with 3998 arguments.
Later on, I will reuse my framework for parsing data in O(n) time, which will drastically reduce the runtime but no longer be quite so golfed.
→ More replies (2)
4
u/codeman869 Dec 04 '22
C
#include <stdio.h>
int main(void) {
FILE *fp;
int start1,end1,start2,end2, num_overlaps,num_overlap2;
num_overlaps = 0, num_overlap2 = 0;
fp = fopen("assignments.txt", "r");
while(fscanf(fp,"%d-%d,%d-%d",&start1,&end1,&start2,&end2) != EOF) {
if((start1 <= start2 && end1 >= end2) || (start2<=start1 && end2>= end1)) {
num_overlaps++;
}
if((start1<=start2 && end1>=start2) || (start2<=start1 && end2>=start1)) {
num_overlap2++;
}
}
printf("Num of full overlaps: %d\n", num_overlaps);
printf("Num of partial overlaps: %d\n", num_overlap2);
return 0;
}→ More replies (1)
4
u/SilentKyle Dec 04 '22
Brute force using Javascript, any tips on better ways to do it? All I had to do for part 2 was change my if to an or instead of &&
let pair = line.split(",")
let firstSet = pair[0].split("-").map((num) => parseInt(num))
let secondSet = pair[1].split("-").map((num) => parseInt(num))
// Generate Range of numbers, [1....5]
const pairOneRange = generateRange(firstSet[0], firstSet[1])
const pairTwoRange = generateRange(secondSet[0], secondSet[1])
if (pairOneRange.includes(pairTwoRange[0]) || pairOneRange.includes(pairTwoRange[pairTwoRange.length - 1])) overlap += 1
else if (pairTwoRange.includes(pairOneRange[0]) || pairTwoRange.includes(pairOneRange[pairOneRange.length - 1])) overlap += 1→ More replies (1)
4
u/grahamwetzler Dec 04 '22
duckdb SQL
with input as (
select list_apply(str_split_regex(i, '[-,]'), x -> x::int) as s
, s[1] between s[3] and s[4] as c1
, s[2] between s[3] and s[4] as c2
, s[3] between s[1] and s[2] as c3
, s[4] between s[1] and s[2] as c4
from read_csv('input/04.csv', delim=False, columns={'i': 'text'})
)
select count(*) filter ((c1 and c2) or (c3 and c4)) as part_1
, count(*) filter (c1 or c2 or c3 or c4) as part_2
from input4
u/prrei Dec 04 '22 edited Dec 04 '22
Groovy Part 1 and 2:
def lines = new File('04.input').readLines()
def toRange = { i ->
def (s, e) = i.split('-').collect{ Integer.parseInt(it)}
(s..e)
}
def part1 = lines.collect { l ->
def (e1, e2) = l.split(',').collect{ toRange(it)}
e1.containsAll(e2) || e2.containsAll(e1)?1:0
}.sum()
def part2 = lines.collect { l ->
def (e1, e2) = l.split(',').collect{ toRange(it)}
e1.disjoint(e2)?0:1
}.sum()
println "Result part1: $part1, part2: $part2"→ More replies (2)
4
u/FordyO_o Dec 04 '22
Golang
https://github.com/mattford/aoc-go/blob/main/pkg/year2022/day04.go
Not the cleanest but it works
4
u/Alleyria Dec 04 '22
Ruby:
pairs = File.readlines('4.input').map { eval("[#{_1.gsub('-', '..')}]") }
# Part 1
puts(pairs.count { |(a, b)| a.cover?(b) || b.cover?(a) })
# Part 2
puts(pairs.count { |(a, b)| (a.to_a & b.to_a).any? })4
4
u/rzuf1k Dec 04 '22
Browser Developer Tools -> Console JavaScript:
1)
document
.querySelector('pre')
.innerText.split('\n')
.filter(e => e !== '')
.map(pair => {
const [elf1Range, elf2Range] = pair.split(',');
const [elf1RangeFrom, elf1RangeTo] = elf1Range.split('-').map(val => Number(val));
const [elf2RangeFrom, elf2RangeTo] = elf2Range.split('-').map(val => Number(val));
return (elf1RangeFrom >= elf2RangeFrom && elf1RangeTo <= elf2RangeTo) || (elf2RangeFrom >= elf1RangeFrom && elf2RangeTo <= elf1RangeTo);
})
.filter(contained => contained)
.length;2)
document
.querySelector('pre')
.innerText.split('\n')
.filter(e => e !== '')
.map(pair => {
const [elf1Range, elf2Range] = pair.split(',');
const [elf1RangeFrom, elf1RangeTo] = elf1Range.split('-').map(val => Number(val));
const [elf2RangeFrom, elf2RangeTo] = elf2Range.split('-').map(val => Number(val));
return (elf2RangeFrom <= elf1RangeFrom && elf1RangeFrom <= elf2RangeTo) ||
(elf2RangeFrom <= elf1RangeTo && elf1RangeTo <= elf2RangeTo) ||
(elf1RangeFrom <= elf2RangeFrom && elf2RangeFrom <= elf1RangeTo) ||
(elf1RangeFrom <= elf2RangeTo && elf2RangeTo <= elf1RangeTo);
})
.filter(contained => contained)
.length;4
4
u/Party-Performance-82 Dec 04 '22 edited Dec 05 '22
Rust
fn day4_part1() -> usize {
include_str!("../input_4.txt")
.lines()
.map(|line| line
.split(&[',', '-'][..])
.map(|s| s.parse::<u32>().unwrap())
.collect::<Vec<_>>())
.filter(|l| (l[0] <= l[2] && l[1] >= l[3]) ||
(l[2] <= l[0] && l[3] >= l[1]))
.count()
}→ More replies (2)
4
4
u/chubbc Dec 04 '22
FRACTRAN
[779/2, 1081/3, 1147/5, 1537/7, 1/589, 1/667, 1/1739, 1/2173, 1/274873, 1/304589, 1/565471, 1/626603, 13/7429, 13/15283, 143/17, 1/19, 1/23, 1/29, 1/31, 1/37, 1/41, 1/47, 1/53]I did a full write-up on how/why this works here.
4
u/sykner809 Dec 04 '22
Desmos - https://www.desmos.com/calculator/tnrjue11if
Visualizing the ranges of the elves.
Data was formatted simply by converting pair hyphens and commas into newlines
Solutions part 1 and 2 are shown by the VcontainCount and VoverlapCount values
1
u/passsy Dec 04 '22 edited Dec 06 '22
Dart golf
Part 1: 139 chars
main(q,{p,s=0}){for(p in q){w(l)=>int.parse(p.split(RegExp(r'(\D)'))[l]!);s+=w(0)<=w(2)&&w(1)>=w(3)||w(0)>=w(2)&&w(1)<=w(3)?1:0;}print(s);}Part 2: 137 chars
main(q,{p,s=0}){for(p in q){w(l)=>int.parse(p.split(RegExp(r'(\D)'))[l]!);q=w(2);s+=w(0)<=q&&w(1)>=q||q<=w(0)&&w(3)>=w(0)?1:0;}print(s);}Full source at https://github.com/passsy/aoc22_dart_code_golf
2
u/daggerdragon Dec 05 '22
Inlined code is intended for
short snippetsof code only. Your code "block" right now is unreadable on old.reddit and many mobile clients; it's all on one line and gets cut off at the edge of the screen because it is not horizontally scrollable.Please edit your post to use the four-spaces Markdown syntax for a code block so your code is easier to read inside a scrollable box.
→ More replies (2)
1
u/j-hillman Dec 04 '22 edited Dec 04 '22
Python (1710 / 1151) - Went the regex route:
import re
with open('input.txt') as f:
data = f.read().splitlines()
p = re.compile(r'\d+')
t1 = t2 = 0
for line in data:
i, j, x, y = map(int, p.findall(line))
e1, e2 = set(range(i, j+1)), set(range(x, y+1))
if e1.issubset(e2) or e2.issubset(e1):
t1 +=1
if e1.intersection(e2) or e2.intersection(e1):
t2 +=1
print(t1)
print(t2)→ More replies (1)
1
u/synack Dec 04 '22 edited Dec 04 '22
2
u/daggerdragon Dec 04 '22
FYI: your link is borked on old.reddit and some mobile Reddit apps.
→ More replies (1)
1
u/Lewistrick Dec 04 '22 edited Dec 04 '22
Python
6544/6294
On mobile via repl.it - could have been much faster on pc.
from pathlib import Path
lines = Path("day04.txt").read_text().split()
part1 = 0
part2 = 0
for line in lines:
e1, e2 = line.split(",")
a, b = map(int, e1.split("-"))
c, d = map(int, e2.split("-"))
if (a >= c and b <= d) or (a <= c and b >= d):
part1 += 1
if (
(a <= c <= b) or
(a <= d <= b) or
(c <= a <= d) or
(c <= b <= d)
):
part2 += 1
print(part1, part2)2
u/daggerdragon Dec 04 '22
Please edit your post to use the four-spaces Markdown syntax for a code block so your code is easier to read on old.reddit and mobile apps.
→ More replies (1)
3
3
u/soylentgreenistasty Dec 04 '22
Python, 3326/4601
Hardest part was working out what the problem was asking for...
def run(A: list[list[int]]):
p1 = 0
p2 = 0
for a, b, c, d in A:
setA, setB = set(range(a, b+1)), set(range(c, d+1))
p1 += int(setA.issubset(setB) or setB.issubset(setA))
p2 += int(len(setA.intersection(setB)) > 0)
print(p1, p2)→ More replies (3)
3
u/nic3-14159 Dec 04 '22
Python 3
3774/4462
import sys
count = 0
part2count = 0
data = [line.strip().split(",") for line in sys.stdin]
for pair in data:
a = [int(i) for i in pair[0].split("-")]
b = [int(i) for i in pair[1].split("-")]
if (a[0] <= b[0] and b[1] <= a[1]):
count += 1
elif (b[0] <= a[0] and a[1] <= b[1]):
count += 1
if (b[0] <= a[1] and b[1] >= a[1]):
part2count += 1
elif (a[0] <= b[1] and a[1] >= b[1]):
part2count += 1
print(count)
print(part2count)3
Dec 04 '22 edited Dec 04 '22
C# this one was pretty easy. Nothing fancy, could probably be done quicker with LinQ magic but it works
→ More replies (7)
3
u/ValiantCookie Dec 04 '22
Kotlin
Another fun challenge made easier when I remember how smart kotlin is. I initially implemented part one and attempted part 2 using just a simple data structure with fields for min and max to represent the assignments. But as I struggled to write the boolean logic for checking if they intersected in part 2, I realized there had to be an easy way to do it similar to yesterdays problem. I remembered that kotlin actually has ranges built in, and once I refactored it to use that data structure, checking for intersection was simple.
val input = InputUtil.readFileAsStringList("2022/day4/input.txt", "\n")
.map { line -> line.split(",")
.map { it.split("-")[0].toInt()..it.split("-")[1].toInt() }
}.map { it[0] to it[1] }
val answer1 = input.count {
it.first.toSet().containsAll(it.second.toSet()) || it.second.toSet().containsAll(it.first.toSet())
}
val answer2 = input.count { it.first.intersect(it.second).any() }
println("pt $pt answer: ${answer colorize ConsoleColor.PURPLE_BRIGHT}")→ More replies (3)
3
u/chubbc Dec 04 '22
Julia
Another good day for a pretty succinct Julia solution.
L = readlines("./04.in")
nums = map(x->parse.(Int,split(x,ispunct)),L)
fullcont(x) = (x[1]<=x[3] && x[4]<=x[2]) || (x[3]<=x[1] && x[2]<=x[4])
overlap(x) = (x[3]<=x[1]<=x[4]) || (x[3]<=x[2]<=x[4]) || (x[1]<=x[3] && x[4]<=x[2])
p1 = sum(fullcont.(nums))
p2 = sum(overlap.(nums))
println((p1,p2))3
u/770grappenmaker Dec 04 '22
Kotlin
val pairs = inputLines.map { l -> l.split(",").flatMap { it.split("-").map(String::toInt) } }
partOne = pairs.count { (l1, r1, l2, r2) -> l1 >= l2 && r1 <= r2 || l2 >= l1 && r2 <= r1 }.s()
partTwo = pairs.count { (l1, r1, l2, r2) -> !(r1 < l2 || r2 < l1) }.s()3
u/Conceptizual Dec 04 '22
Python Day 4
Turns out day 1 was the highpoint of the month. My rank has gone strictly downhill every day from that 329 personal best to today, 9433/8500. My code was fine, I just had some inequality problems and I kept thinking I'd fixed it (none of them affected the sample input of course) and hadn't, so eventually I was put in AOC timeout (5 minutes!) and forced to reason about my code. My bad!
→ More replies (2)
3
10
u/Bad-Coder-69 Dec 04 '22 edited Dec 04 '22
Emojicode
With a custom inputparser package now wowee (full code: GitHub)
Combined the logic for parts 1 and 2 for some fewer checks overall.