Added day 11 and 12
This commit is contained in:
+114
@@ -0,0 +1,114 @@
|
||||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
const input = "890 0 1 935698 68001 3441397 7221 27";
|
||||
const numberT = u64;
|
||||
|
||||
// Passed to a weird while loop instead of recurcive function because I run into limitation, too much recursion :/
|
||||
|
||||
const Stone = struct {
|
||||
number: numberT,
|
||||
next: ?*Stone = null,
|
||||
|
||||
fn step(self: *Stone, allocator: std.mem.Allocator) !void {
|
||||
var current = self;
|
||||
while (true) {
|
||||
if (current.number == 0) {
|
||||
current.number = 1;
|
||||
if (current.next) |right_stone| {
|
||||
current = right_stone;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (digitCount(current.number) % 2 == 0) {
|
||||
const new_value = splitNumber(current.number);
|
||||
const new_stone = try allocator.create(Stone);
|
||||
new_stone.* = Stone{ .number = new_value[1], .next = current.next };
|
||||
current.number = new_value[0];
|
||||
current.next = new_stone;
|
||||
if (new_stone.next) |right_stone| {
|
||||
current = right_stone;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
current.number *= 2024;
|
||||
if (current.next) |right_stone| {
|
||||
current = right_stone;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn printStone(self: Stone) void {
|
||||
print("{d} ", .{self.number});
|
||||
if (self.right) |right_stone| {
|
||||
right_stone.printStone();
|
||||
} else {
|
||||
print("\n", .{});
|
||||
}
|
||||
}
|
||||
|
||||
fn count(self: *Stone, total: *usize) void {
|
||||
var current = self;
|
||||
while (true) {
|
||||
total.* += 1;
|
||||
if (current.next) |right_stone| {
|
||||
current = right_stone;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
|
||||
var iter = std.mem.splitAny(u8, input, " ");
|
||||
const first_stone = try allocator.create(Stone);
|
||||
first_stone.* = Stone{ .number = try std.fmt.parseInt(numberT, iter.next().?, 10) };
|
||||
|
||||
var last_stone = first_stone;
|
||||
while (iter.next()) |number| {
|
||||
const new_stone = try allocator.create(Stone);
|
||||
new_stone.* = Stone{ .number = try std.fmt.parseInt(numberT, number, 10) };
|
||||
last_stone.next = new_stone;
|
||||
last_stone = new_stone;
|
||||
}
|
||||
|
||||
for (0..25) |_| try first_stone.step(allocator);
|
||||
|
||||
var total: usize = 0;
|
||||
first_stone.count(&total);
|
||||
try std.testing.expectEqual(194782, total);
|
||||
}
|
||||
|
||||
fn digitCount(num: numberT) usize {
|
||||
if (num == 0) return 1;
|
||||
|
||||
var n = num;
|
||||
var count: usize = 0;
|
||||
while (n != 0) : (n = @divFloor(n, 10)) {
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
fn splitNumber(num: numberT) [2]numberT {
|
||||
const numDigits = digitCount(num);
|
||||
const halfDigits = numDigits / 2;
|
||||
|
||||
var divisor: numberT = 1;
|
||||
for (halfDigits) |_| {
|
||||
divisor *= 10;
|
||||
}
|
||||
|
||||
const left = @divFloor(num, divisor);
|
||||
const right = num % divisor;
|
||||
|
||||
return [2]numberT{ left, right };
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn main() !void {
|
||||
var map = std.AutoHashMap(usize, usize).init(std.heap.page_allocator);
|
||||
defer map.deinit();
|
||||
|
||||
for ([_]usize{ 890, 0, 1, 935698, 68001, 3441397, 7221, 27 }) |n| try map.put(n, (map.get(n) orelse 0) + 1);
|
||||
|
||||
for (0..75) |_| try step(&map);
|
||||
try std.testing.expectEqual(233007586663131, countStone(map));
|
||||
}
|
||||
|
||||
fn step(map: *std.AutoHashMap(usize, usize)) !void {
|
||||
var old_map = try map.clone();
|
||||
defer old_map.deinit();
|
||||
|
||||
map.clearRetainingCapacity();
|
||||
var iter = old_map.iterator();
|
||||
while (iter.next()) |entry| {
|
||||
if (entry.key_ptr.* == 0) {
|
||||
try map.put(1, (map.get(1) orelse 0) + entry.value_ptr.*);
|
||||
} else if (countDigit(entry.key_ptr.*) % 2 == 0) {
|
||||
const splits = splitDigit(entry.key_ptr.*);
|
||||
try map.put(splits[0], (map.get(splits[0]) orelse 0) + entry.value_ptr.*);
|
||||
try map.put(splits[1], (map.get(splits[1]) orelse 0) + entry.value_ptr.*);
|
||||
} else {
|
||||
try map.put(entry.key_ptr.* * 2024, (map.get(entry.key_ptr.* * 2024) orelse 0) + entry.value_ptr.*);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn countDigit(number: usize) usize {
|
||||
var n: usize = number;
|
||||
var count: usize = 0;
|
||||
while (n != 0) : (count += 1) n = @divFloor(n, 10);
|
||||
return count;
|
||||
}
|
||||
|
||||
fn splitDigit(number: usize) [2]usize {
|
||||
const divider = std.math.pow(usize, 10, (countDigit(number) / 2));
|
||||
return [2]usize{ @divFloor(number, divider), number % divider };
|
||||
}
|
||||
|
||||
fn countStone(map: std.AutoHashMap(usize, usize)) usize {
|
||||
var total: usize = 0;
|
||||
var iter = map.valueIterator();
|
||||
while (iter.next()) |entry| total += entry.*;
|
||||
return total;
|
||||
}
|
||||
Reference in New Issue
Block a user