day9_common.carbon 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. // https://adventofcode.com/2024/day/9
  5. library "day9_common";
  6. import Core library "io";
  7. import Core library "range";
  8. import library "io_utils";
  9. class SectorList {
  10. fn Read() -> SectorList {
  11. returned var me: SectorList;
  12. me.size = 0;
  13. var sector: i32 = 0;
  14. var used: bool = true;
  15. // TODO: An assignment expression would be useful here.
  16. var c: i32 = ReadChar();
  17. while (c != Core.EOF() and c != 0xA) {
  18. let v: i32 = if used then sector else -1;
  19. for (_: i32 in Core.Range(c - 0x30)) {
  20. me.data[me.size] = v;
  21. ++me.size;
  22. }
  23. if (used) {
  24. ++sector;
  25. }
  26. used = not used;
  27. c = ReadChar();
  28. }
  29. return var;
  30. }
  31. fn DefragBlocks[addr self: Self*]() {
  32. var i: i32 = 0;
  33. var j: i32 = self->size - 1;
  34. while (j > i) {
  35. if (self->data[i] != -1) {
  36. ++i;
  37. } else if (self->data[j] == -1) {
  38. --j;
  39. } else {
  40. self->data[i] = self->data[j];
  41. ++i;
  42. --j;
  43. }
  44. }
  45. self->size = j;
  46. }
  47. fn HasSpace[addr self: Self*](start: i32, size: i32) -> bool {
  48. for (i: i32 in Core.InclusiveRange(start, start + size - 1)) {
  49. if (self->data[i] != -1) {
  50. return false;
  51. }
  52. }
  53. return true;
  54. }
  55. fn Fill[addr self: Self*](start: i32, size: i32, sector: i32) {
  56. for (i: i32 in Core.InclusiveRange(start, start + size - 1)) {
  57. self->data[i] = sector;
  58. }
  59. }
  60. fn DefragFiles[addr self: Self*]() {
  61. var j: i32 = self->size - 1;
  62. while (j >= 0) {
  63. // Skip empty sectors.
  64. while (j >= 0 and self->data[j] == -1) {
  65. --j;
  66. }
  67. // Find the file size and sector and delete the file.
  68. let last: i32 = j;
  69. let sector: i32 = self->data[last];
  70. while (j >= 0 and self->data[j] == sector) {
  71. self->data[j] = -1;
  72. --j;
  73. }
  74. let first: i32 = j + 1;
  75. let size: i32 = last - first + 1;
  76. // Find the first available space for the file.
  77. var i: i32 = 0;
  78. while (not self->HasSpace(i, size)) {
  79. ++i;
  80. if (i + size > first) {
  81. // If it doesn't fit to the left of its old position, put it back
  82. // where it was.
  83. i = first;
  84. }
  85. }
  86. // Insert it.
  87. self->Fill(i, size, sector);
  88. }
  89. }
  90. fn Checksum[self: Self]() -> i64 {
  91. var total: i64 = 0;
  92. for (i: i32 in Core.Range(self.size)) {
  93. if (self.data[i] != -1) {
  94. total = total + ((i * self.data[i]) as i64);
  95. }
  96. }
  97. return total;
  98. }
  99. var data: array(i32, 200000);
  100. var size: i32;
  101. }