mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 19:51:09 +01:00
115 lines
2.7 KiB
Plaintext
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;
|
|
}
|