Files
carbon-lang/examples/advent2024/day9_common.carbon
T
2025-06-26 20:13:07 +00:00

115 lines
2.7 KiB
Plaintext

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// https://adventofcode.com/2024/day/9
library "day9_common";
import Core library "io";
import Core library "range";
import library "io_utils";
class SectorList {
fn Read() -> SectorList {
returned var me: SectorList;
me.size = 0;
var sector: i32 = 0;
var used: bool = true;
// TODO: An assignment expression would be useful here.
var c: i32 = ReadChar();
while (c != Core.EOF() and c != 0xA) {
let v: i32 = if used then sector else -1;
for (_: i32 in Core.Range(c - 0x30)) {
me.data[me.size] = v;
++me.size;
}
if (used) {
++sector;
}
used = not used;
c = ReadChar();
}
return var;
}
fn DefragBlocks[addr self: Self*]() {
var i: i32 = 0;
var j: i32 = self->size - 1;
while (j > i) {
if (self->data[i] != -1) {
++i;
} else if (self->data[j] == -1) {
--j;
} else {
self->data[i] = self->data[j];
++i;
--j;
}
}
self->size = j;
}
fn HasSpace[addr self: Self*](start: i32, size: i32) -> bool {
for (i: i32 in Core.InclusiveRange(start, start + size - 1)) {
if (self->data[i] != -1) {
return false;
}
}
return true;
}
fn Fill[addr self: Self*](start: i32, size: i32, sector: i32) {
for (i: i32 in Core.InclusiveRange(start, start + size - 1)) {
self->data[i] = sector;
}
}
fn DefragFiles[addr self: Self*]() {
var j: i32 = self->size - 1;
while (j >= 0) {
// Skip empty sectors.
while (j >= 0 and self->data[j] == -1) {
--j;
}
// Find the file size and sector and delete the file.
let last: i32 = j;
let sector: i32 = self->data[last];
while (j >= 0 and self->data[j] == sector) {
self->data[j] = -1;
--j;
}
let first: i32 = j + 1;
let size: i32 = last - first + 1;
// Find the first available space for the file.
var i: i32 = 0;
while (not self->HasSpace(i, size)) {
++i;
if (i + size > first) {
// If it doesn't fit to the left of its old position, put it back
// where it was.
i = first;
}
}
// Insert it.
self->Fill(i, size, sector);
}
}
fn Checksum[self: Self]() -> i64 {
var total: i64 = 0;
for (i: i32 in Core.Range(self.size)) {
if (self.data[i] != -1) {
total = total + ((i * self.data[i]) as i64);
}
}
return total;
}
var data: array(i32, 200000);
var size: i32;
}