87 lines
2.8 KiB
Zig
87 lines
2.8 KiB
Zig
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];
|
|
}
|