Added day 9
Forgot to push yesterday :/
This commit is contained in:
parent
568e6e9b4a
commit
832bef6497
@ -16,6 +16,8 @@ const d71 = @import("day7/part1.zig");
|
||||
const d72 = @import("day7/part2.zig");
|
||||
const d81 = @import("day8/part1.zig");
|
||||
const d82 = @import("day8/part2.zig");
|
||||
const d91 = @import("day9/part1.zig");
|
||||
const d92 = @import("day9/part2.zig");
|
||||
|
||||
const NUMBER_OF_RUN = 1000;
|
||||
|
||||
@ -52,6 +54,9 @@ pub fn main() !void {
|
||||
try benchmark(d81.main, 8, 1);
|
||||
try benchmark(d82.main, 8, 2);
|
||||
separator();
|
||||
try benchmark(d91.main, 9, 1);
|
||||
try benchmark(d92.main, 9, 2);
|
||||
separator();
|
||||
print("| Total | {d: >8} ± {d: <6.2} | {d:>8} | {d:>8} |\n", .{ total_mean, total_std_dev, total_min, total_max });
|
||||
separator();
|
||||
}
|
||||
|
1
day9/input
Normal file
1
day9/input
Normal file
File diff suppressed because one or more lines are too long
77
day9/part1.zig
Normal file
77
day9/part1.zig
Normal file
@ -0,0 +1,77 @@
|
||||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
const file = @embedFile("input");
|
||||
|
||||
// Take first free space and last file and swap
|
||||
|
||||
const Block = struct {
|
||||
id: ?usize,
|
||||
type_: enum { file, empty },
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var total_file_block: usize = 0;
|
||||
var total_free_block: usize = 0;
|
||||
|
||||
var list = std.ArrayList(Block).init(allocator);
|
||||
for (file[0 .. file.len - 1], 0..) |c, i| {
|
||||
const number = c - '0';
|
||||
if (i % 2 == 0) {
|
||||
total_file_block += number;
|
||||
for (0..number) |_| try list.append(Block{ .id = @divFloor(i, 2), .type_ = .file });
|
||||
} else {
|
||||
total_free_block += number;
|
||||
for (0..number) |_| try list.append(Block{ .id = null, .type_ = .empty });
|
||||
}
|
||||
}
|
||||
|
||||
sort(list.items, total_file_block);
|
||||
try std.testing.expectEqual(6401092019345, checksum(list.items, total_file_block));
|
||||
}
|
||||
|
||||
fn checksum(list: []Block, total_file_block: usize) usize {
|
||||
var total: usize = 0;
|
||||
for (list[0..total_file_block], 0..) |block, i| total += block.id.? * i;
|
||||
return total;
|
||||
}
|
||||
|
||||
fn sort(list: []Block, total_file_block: usize) void {
|
||||
var left_index: usize = 0;
|
||||
var right_index: usize = list.len - 1;
|
||||
var block_buff: Block = undefined;
|
||||
|
||||
// I dont want a while loop where I check the list everytime, I need to know the number of swap that I need to do and use a for loop
|
||||
// Like that I dont need to check if the list is sorted, it will be at the end of the for loop
|
||||
// To know how many to move I need to know the number of file block and free block. This I can do it when I parse the first time.
|
||||
// Then I can parse the list one time and for each type not at the right position, it's a swap, then divide by 2
|
||||
|
||||
for (0..total_swap_needed(list, total_file_block)) |_| {
|
||||
left_index = next_empty_block(list, left_index).?;
|
||||
right_index = next_file_block(list, right_index).?;
|
||||
|
||||
block_buff = list[left_index];
|
||||
list[left_index] = list[right_index];
|
||||
list[right_index] = block_buff;
|
||||
}
|
||||
}
|
||||
|
||||
fn next_empty_block(list: []Block, index: usize) ?usize {
|
||||
for (index..list.len) |i| if (list[i].type_ == .empty) return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
fn next_file_block(list: []Block, index: usize) ?usize {
|
||||
for (0..index) |i| if (list[index - i].type_ == .file) return (index - i);
|
||||
return null;
|
||||
}
|
||||
|
||||
fn total_swap_needed(list: []Block, total_file_block: usize) usize {
|
||||
var total: usize = 0;
|
||||
for (list, 0..) |block, i| {
|
||||
if ((block.type_ == .file and i > total_file_block) or (block.type_ == .empty and i < total_file_block)) total += 1;
|
||||
}
|
||||
return @divFloor(total, 2);
|
||||
}
|
86
day9/part2.zig
Normal file
86
day9/part2.zig
Normal file
@ -0,0 +1,86 @@
|
||||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
const file = @embedFile("input");
|
||||
//const file = "2333133121414131402\n";
|
||||
|
||||
// I think I just need to change both next function
|
||||
// The e;pty block now take a size argument
|
||||
// And the file take the current file index
|
||||
|
||||
const Block = struct {
|
||||
id: ?usize,
|
||||
type_: enum { file, empty },
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const max_file_index = @divFloor(file.len - 1, 2);
|
||||
|
||||
// 1. create the list
|
||||
var list = std.ArrayList(Block).init(allocator);
|
||||
defer list.deinit();
|
||||
for (file[0 .. file.len - 1], 0..) |c, i| {
|
||||
if (i % 2 == 0) {
|
||||
for (0..c - '0') |_| try list.append(Block{ .id = @divFloor(i, 2), .type_ = .file });
|
||||
} else {
|
||||
for (0..c - '0') |_| try list.append(Block{ .id = null, .type_ = .empty });
|
||||
}
|
||||
}
|
||||
|
||||
sort(list.items, max_file_index);
|
||||
try std.testing.expectEqual(6431472344710, checksum(list.items));
|
||||
}
|
||||
|
||||
fn checksum(list: []Block) usize {
|
||||
var total: usize = 0;
|
||||
for (list, 0..) |block, i| total += if (block.id) |id| id * i else 0;
|
||||
return total;
|
||||
}
|
||||
|
||||
fn sort(list: []Block, max_file_index: usize) void {
|
||||
for (0..max_file_index) |i| {
|
||||
const result = file_size_index(list, max_file_index - i) orelse continue;
|
||||
const index = empty_space(list, result[0]) orelse continue;
|
||||
if (index > result[1]) continue;
|
||||
swap_memory(list, result[1], index, result[0]);
|
||||
}
|
||||
}
|
||||
|
||||
fn empty_space(list: []Block, size: usize) ?usize {
|
||||
var mesuring: bool = false;
|
||||
var len: usize = 0;
|
||||
for (list, 0..) |block, i| {
|
||||
if (mesuring and len == size) return (i - len);
|
||||
if (block.type_ == .empty and !mesuring) {
|
||||
mesuring = true;
|
||||
len = 1;
|
||||
} else if (block.type_ == .file and mesuring) {
|
||||
mesuring = false;
|
||||
len = 0;
|
||||
} else if (block.type_ == .empty and mesuring) len += 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
fn file_size_index(list: []Block, file_index: usize) ?[2]usize {
|
||||
var mesuring: bool = false;
|
||||
var len: usize = 0;
|
||||
for (list, 0..) |block, i| {
|
||||
if (!mesuring and block.id == file_index) {
|
||||
mesuring = true;
|
||||
len = 1;
|
||||
} else if (mesuring and (block.type_ != .empty and block.type_ == .file and block.id.? == file_index)) {
|
||||
len += 1;
|
||||
} else if (mesuring and (block.type_ == .empty or (block.type_ == .file and block.id.? != file_index))) return [2]usize{ len, i - len };
|
||||
}
|
||||
return [2]usize{ len, list.len - len };
|
||||
}
|
||||
|
||||
fn swap_memory(list: []Block, from: usize, to: usize, len: usize) void {
|
||||
var buf: [9]Block = undefined;
|
||||
for (to..to + len, 0..len) |i, j| buf[j] = list[i];
|
||||
for (to..to + len, from..from + len) |i, j| list[i] = list[j];
|
||||
for (from..from + len, 0..len) |i, j| list[i] = buf[j];
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user