113 lines
2.7 KiB
C
113 lines
2.7 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define char2i(c) (c - 48)
|
|
#define MAX_DISK_SIZE 1024*1024
|
|
|
|
int main() {
|
|
char c;
|
|
|
|
uint32_t *disk = calloc(MAX_DISK_SIZE, sizeof(disk[0]));
|
|
int disk_size = 0;
|
|
uint32_t file_count = 0;
|
|
int is_file = 1;
|
|
|
|
while ((c = getchar()) != EOF) {
|
|
int n = char2i(c);
|
|
uint32_t data = is_file ? file_count++ : UINT32_MAX;
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
disk[disk_size++] = data;
|
|
}
|
|
|
|
is_file = !is_file;
|
|
}
|
|
|
|
// Create copy
|
|
uint32_t *disk_copy = calloc(disk_size, sizeof(disk_copy[0]));
|
|
memcpy(disk_copy, disk, disk_size * sizeof(disk[0]));
|
|
|
|
int last_empty = 0;
|
|
int inserted_back = 0;
|
|
for (;;) {
|
|
// Find next empty space
|
|
while (disk_copy[last_empty] != UINT32_MAX && last_empty < disk_size - inserted_back - 1) last_empty++;
|
|
|
|
if (last_empty >= disk_size - inserted_back - 1) {
|
|
break;
|
|
}
|
|
|
|
disk_copy[last_empty] = disk_copy[disk_size - inserted_back - 1];
|
|
disk_copy[disk_size - inserted_back - 1] = UINT32_MAX;
|
|
inserted_back++;
|
|
}
|
|
|
|
uint64_t checksum = 0;
|
|
|
|
for (int i = 0; i < disk_size; i++) {
|
|
if (disk_copy[i] != UINT32_MAX) {
|
|
checksum += disk_copy[i] * i;
|
|
}
|
|
}
|
|
|
|
free(disk_copy);
|
|
|
|
printf("%lu\n", checksum);
|
|
|
|
// Part two
|
|
for (int i = file_count - 1; i >= 0; i--) {
|
|
// Get file size inefficiently
|
|
int file_size = 0;
|
|
int file_begin = 0;
|
|
for (int j = 0; j < disk_size; j++) {
|
|
if (disk[j] == i) {
|
|
if (file_size == 0) {
|
|
file_begin = j;
|
|
}
|
|
file_size++;
|
|
}
|
|
}
|
|
|
|
// Find empty space
|
|
for (int j = 0; j < disk_size; j++) {
|
|
// We only place files left
|
|
if (disk[j] == i) {
|
|
break;
|
|
}
|
|
|
|
if (disk[j] == UINT32_MAX) {
|
|
// Let's see if we have enough space
|
|
int fit = 1;
|
|
for (int k = 0; k < file_size; k++) {
|
|
if (disk[j + k] != UINT32_MAX) {
|
|
fit = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (fit) {
|
|
for (int k = 0; k < file_size; k++) {
|
|
disk[j + k] = i;
|
|
disk[file_begin + k] = UINT32_MAX;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
checksum = 0;
|
|
|
|
for (int i = 0; i < disk_size; i++) {
|
|
if (disk[i] != UINT32_MAX) {
|
|
checksum += disk[i] * i;
|
|
}
|
|
}
|
|
|
|
free(disk);
|
|
|
|
printf("%lu\n", checksum);
|
|
}
|