From 10378f2d891aa173e308bc70781b648dd3f808ad Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 13 Dec 2024 01:17:06 +0000 Subject: [PATCH] Refactor examples and add a README. --- examples/advent2024/BUILD | 15 +++- examples/advent2024/README.md | 17 ++++ examples/advent2024/day1_common.carbon | 21 +++++ examples/advent2024/day1_part1.carbon | 120 +------------------------ examples/advent2024/day1_part2.carbon | 120 +------------------------ examples/advent2024/io_utils.carbon | 73 +++++++++++++++ examples/advent2024/sort.carbon | 43 +++++++++ 7 files changed, 171 insertions(+), 238 deletions(-) create mode 100644 examples/advent2024/README.md create mode 100644 examples/advent2024/day1_common.carbon create mode 100644 examples/advent2024/io_utils.carbon create mode 100644 examples/advent2024/sort.carbon diff --git a/examples/advent2024/BUILD b/examples/advent2024/BUILD index 0a2ee48f0d06f..c38b1cb61929d 100644 --- a/examples/advent2024/BUILD +++ b/examples/advent2024/BUILD @@ -4,12 +4,23 @@ load("//bazel/carbon_rules:defs.bzl", "carbon_binary") +utils = [ + "io_utils.carbon", + "sort.carbon", +] + carbon_binary( name = "day1_part1", - srcs = ["day1_part1.carbon"], + srcs = [ + "day1_common.carbon", + "day1_part1.carbon", + ] + utils, ) carbon_binary( name = "day1_part2", - srcs = ["day1_part2.carbon"], + srcs = [ + "day1_common.carbon", + "day1_part2.carbon", + ] + utils, ) diff --git a/examples/advent2024/README.md b/examples/advent2024/README.md new file mode 100644 index 0000000000000..f7bdef6fbd35e --- /dev/null +++ b/examples/advent2024/README.md @@ -0,0 +1,17 @@ +# Advent of Code 2024 + + + +This directory contains sample solutions written in Carbon for +[Advent of Code 2024](https://adventofcode.com/2024/). + +The Carbon toolchain is in a very early state, so these samples frequently need +to work around missing functionality and are not reflective of expected Carbon +style and idioms. Instead, the purpose of these examples are to test the current +state of the toolchain against larger code examples than those that are present +in the toolchain's own tests, to find bugs in the toolchain, and to drive +feature development in the toolchain by presenting somewhat realistic testcases. diff --git a/examples/advent2024/day1_common.carbon b/examples/advent2024/day1_common.carbon new file mode 100644 index 0000000000000..b4c1c21295ee3 --- /dev/null +++ b/examples/advent2024/day1_common.carbon @@ -0,0 +1,21 @@ +// 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 + +library "day1_common"; + +import library "io_utils"; + +// Read a sequence of lines each containing a pair of numbers into two arrays. +// Returns the number of lines read. +fn ReadInputs(ap: [i32; 1000]*, bp: [i32; 1000]*) -> i32 { + var n: i32 = 0; + var a: i32; + var b: i32; + while (n < 1000 and ReadInt(&a) and SkipSpaces() and ReadInt(&b) and SkipNewline()) { + (*ap)[n] = a; + (*bp)[n] = b; + ++n; + } + return n; +} diff --git a/examples/advent2024/day1_part1.carbon b/examples/advent2024/day1_part1.carbon index e0fac756030ca..b1d1f411e8aab 100644 --- a/examples/advent2024/day1_part1.carbon +++ b/examples/advent2024/day1_part1.carbon @@ -4,128 +4,12 @@ import Core library "io"; -var push_back: i32 = Core.EOF(); - -fn ReadCharRaw() -> i32 = "read.char"; - -fn ReadChar() -> i32 { - var next: i32 = push_back; - push_back = Core.EOF(); - if (next == Core.EOF()) { - next = ReadCharRaw(); - } - return next; -} - -fn UnreadChar(c: i32) { - // TODO: assert(push_back == Core.EOF()); - push_back = c; -} - -fn ReadInt(p: i32*) -> bool { - var read_any_digits: bool = false; - *p = 0; - - while (true) { - var c: i32 = ReadChar(); - if (c < 0x30 or c > 0x39) { - UnreadChar(c); - break; - } - // TODO: Check for overflow. - *p *= 10; - *p += c - 0x30; - read_any_digits = true; - } - return read_any_digits; -} - -fn SkipSpaces() -> bool { - var skipped_any_spaces: bool = false; - while (true) { - var c: i32 = ReadChar(); - if (c != 0x20) { - UnreadChar(c); - break; - } - skipped_any_spaces = true; - } - return skipped_any_spaces; -} - -fn SkipNewline() -> bool { - var c: i32 = ReadChar(); - // Optional carriage return. - if (c == 0x0D) { - c = ReadChar(); - } - // Newline. - if (c == 0x0A) { - return true; - } - // TODO: Unread the CR? - UnreadChar(c); - return false; -} - -// let N:! i32 = 1000; -// TODO: let Array:! type = [i32; N]; - -// Read a sequence of lines each containing a pair of numbers into two arrays. -// Returns the number of lines read. -fn ReadInputs(ap: [i32; 1000]*, bp: [i32; 1000]*) -> i32 { - var n: i32 = 0; - var a: i32; - var b: i32; - while (n < 1000 and ReadInt(&a) and SkipSpaces() and ReadInt(&b) and SkipNewline()) { - (*ap)[n] = a; - (*bp)[n] = b; - ++n; - } - return n; -} - -fn Swap(p: [i32; 1000]*, from: i32, to: i32) { - var tmp: i32 = (*p)[from]; - (*p)[from] = (*p)[to]; - (*p)[to] = tmp; -} - -fn Partition(p: [i32; 1000]*, from_in: i32, to_in: i32) -> i32 { - var pivot_index: i32 = from_in; - var pivot: i32 = (*p)[pivot_index]; - var from: i32 = from_in + 1; - var to: i32 = to_in; - while (from < to) { - if ((*p)[from] <= pivot) { - ++from; - } else if ((*p)[to - 1] > pivot) { - --to; - } else { - // Element at `from` is > pivot, and - // element at `to` is <= pivot. - Swap(p, from, to - 1); - ++from; - --to; - } - } - Swap(p, pivot_index, from - 1); - return from - 1; -} - -fn Quicksort(p: [i32; 1000]*, from: i32, to: i32) { - if (from + 1 >= to) { return; } - var pivot: i32 = Partition(p, from, to); - Quicksort(p, from, pivot); - Quicksort(p, pivot + 1, to); -} +import library "day1_common"; +import library "sort"; fn Abs(n: i32) -> i32 { return if n < 0 then -n else n; } fn Run() { - // TODO: Global initialization is not implemented yet. - push_back = Core.EOF(); - var a: [i32; 1000]; var b: [i32; 1000]; var n: i32 = ReadInputs(&a, &b); diff --git a/examples/advent2024/day1_part2.carbon b/examples/advent2024/day1_part2.carbon index 8736663d90bc9..c6521822a8ec3 100644 --- a/examples/advent2024/day1_part2.carbon +++ b/examples/advent2024/day1_part2.carbon @@ -4,126 +4,10 @@ import Core library "io"; -var push_back: i32 = Core.EOF(); - -fn ReadCharRaw() -> i32 = "read.char"; - -fn ReadChar() -> i32 { - var next: i32 = push_back; - push_back = Core.EOF(); - if (next == Core.EOF()) { - next = ReadCharRaw(); - } - return next; -} - -fn UnreadChar(c: i32) { - // TODO: assert(push_back == Core.EOF()); - push_back = c; -} - -fn ReadInt(p: i32*) -> bool { - var read_any_digits: bool = false; - *p = 0; - - while (true) { - var c: i32 = ReadChar(); - if (c < 0x30 or c > 0x39) { - UnreadChar(c); - break; - } - // TODO: Check for overflow. - *p *= 10; - *p += c - 0x30; - read_any_digits = true; - } - return read_any_digits; -} - -fn SkipSpaces() -> bool { - var skipped_any_spaces: bool = false; - while (true) { - var c: i32 = ReadChar(); - if (c != 0x20) { - UnreadChar(c); - break; - } - skipped_any_spaces = true; - } - return skipped_any_spaces; -} - -fn SkipNewline() -> bool { - var c: i32 = ReadChar(); - // Optional carriage return. - if (c == 0x0D) { - c = ReadChar(); - } - // Newline. - if (c == 0x0A) { - return true; - } - // TODO: Unread the CR? - UnreadChar(c); - return false; -} - -// let N:! i32 = 1000; -// TODO: let Array:! type = [i32; N]; - -// Read a sequence of lines each containing a pair of numbers into two arrays. -// Returns the number of lines read. -fn ReadInputs(ap: [i32; 1000]*, bp: [i32; 1000]*) -> i32 { - var n: i32 = 0; - var a: i32; - var b: i32; - while (n < 1000 and ReadInt(&a) and SkipSpaces() and ReadInt(&b) and SkipNewline()) { - (*ap)[n] = a; - (*bp)[n] = b; - ++n; - } - return n; -} - -fn Swap(p: [i32; 1000]*, from: i32, to: i32) { - var tmp: i32 = (*p)[from]; - (*p)[from] = (*p)[to]; - (*p)[to] = tmp; -} - -fn Partition(p: [i32; 1000]*, from_in: i32, to_in: i32) -> i32 { - var pivot_index: i32 = from_in; - var pivot: i32 = (*p)[pivot_index]; - var from: i32 = from_in + 1; - var to: i32 = to_in; - while (from < to) { - if ((*p)[from] <= pivot) { - ++from; - } else if ((*p)[to - 1] > pivot) { - --to; - } else { - // Element at `from` is > pivot, and - // element at `to` is <= pivot. - Swap(p, from, to - 1); - ++from; - --to; - } - } - Swap(p, pivot_index, from - 1); - return from - 1; -} - -fn Quicksort(p: [i32; 1000]*, from: i32, to: i32) { - if (from + 1 >= to) { return; } - var pivot: i32 = Partition(p, from, to); - Quicksort(p, from, pivot); - Quicksort(p, pivot + 1, to); -} +import library "day1_common"; +import library "sort"; fn Run() { - // TODO: Global initialization is not implemented yet. - push_back = Core.EOF(); - var a: [i32; 1000]; var b: [i32; 1000]; var n: i32 = ReadInputs(&a, &b); diff --git a/examples/advent2024/io_utils.carbon b/examples/advent2024/io_utils.carbon new file mode 100644 index 0000000000000..ce26cbcfe7e69 --- /dev/null +++ b/examples/advent2024/io_utils.carbon @@ -0,0 +1,73 @@ +// 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 + +library "io_utils"; + +import Core library "io"; + +// TODO: Use Core.EOF() rather than 0 as a sentinel here. +// At the moment, 0 is the only value we can initialize a global to, +// so we store the value plus 1 here. +var push_back: i32 = 0; + +fn ReadChar() -> i32 { + var next: i32 = push_back - 1; + push_back = 0; + // TODO: assert(push_back == Core.EOF()); + if (next == Core.EOF()) { + next = Core.ReadChar(); + } + return next; +} + +fn UnreadChar(c: i32) { + // TODO: assert(push_back == Core.EOF()); + push_back = c + 1; +} + +fn ReadInt(p: i32*) -> bool { + var read_any_digits: bool = false; + *p = 0; + + while (true) { + var c: i32 = ReadChar(); + if (c < 0x30 or c > 0x39) { + UnreadChar(c); + break; + } + // TODO: Check for overflow. + *p *= 10; + *p += c - 0x30; + read_any_digits = true; + } + return read_any_digits; +} + +fn SkipSpaces() -> bool { + var skipped_any_spaces: bool = false; + while (true) { + var c: i32 = ReadChar(); + if (c != 0x20) { + UnreadChar(c); + break; + } + skipped_any_spaces = true; + } + return skipped_any_spaces; +} + +fn SkipNewline() -> bool { + var c: i32 = ReadChar(); + // Optional carriage return. + if (c == 0x0D) { + c = ReadChar(); + } + // Newline. + if (c == 0x0A) { + return true; + } + // TODO: Unread the CR? + UnreadChar(c); + return false; +} diff --git a/examples/advent2024/sort.carbon b/examples/advent2024/sort.carbon new file mode 100644 index 0000000000000..c0be66c5a5da4 --- /dev/null +++ b/examples/advent2024/sort.carbon @@ -0,0 +1,43 @@ +// 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 + +library "sort"; + +// TODO: Generalize this for other container types once we implement lowering +// for generic functions. + +fn Swap(p: [i32; 1000]*, from: i32, to: i32) { + var tmp: i32 = (*p)[from]; + (*p)[from] = (*p)[to]; + (*p)[to] = tmp; +} + +fn Partition(p: [i32; 1000]*, from_in: i32, to_in: i32) -> i32 { + var pivot_index: i32 = from_in; + var pivot: i32 = (*p)[pivot_index]; + var from: i32 = from_in + 1; + var to: i32 = to_in; + while (from < to) { + if ((*p)[from] <= pivot) { + ++from; + } else if ((*p)[to - 1] > pivot) { + --to; + } else { + // Element at `from` is > pivot, and + // element at `to` is <= pivot. + Swap(p, from, to - 1); + ++from; + --to; + } + } + Swap(p, pivot_index, from - 1); + return from - 1; +} + +fn Quicksort(p: [i32; 1000]*, from: i32, to: i32) { + if (from + 1 >= to) { return; } + var pivot: i32 = Partition(p, from, to); + Quicksort(p, from, pivot); + Quicksort(p, pivot + 1, to); +}