On Saturday, 2 December 2023 at 13:33:33 UTC, Johannes Miesenhardt wrote:
I am a bloody beginner so if there are any things that are very wrong with this please point them out.

Everything is fine as long as it works and does the job.

The fact that I need a template for accepting both a string and a char[] is very weird but I went with it.

The `string` type is not the same as `char[]`. It's actually `immutable(char)[]`. The differences are explained in the D language spec: https://dlang.org/spec/const3.html#const_and_immutable

Strings can be safely passed around between functions and multiple instances of the same string can share the same memory location, the characters inside of a string are read-only. Whereas character arrays allow read/write access.

Casting between character arrays and strings is a bad idea by design. Converting between strings and character arrays involves allocating memory for a new copy and this happens under the hood when calling `.dup`, `.idup`, `.to!string` or `.byLineCopy`.

I am also curious if there is a better way for the reversible for-loop to happen. I saw foreach and foreach_reverse but I don't think that helps me here, since I swap them out based on a runtime argument.

Below is my solution for the day 1 puzzle, which used https://dlang.org/library/std/range/retro.html to search characters starting from the end:

```D
import std;
void main() {
  auto input = stdin.byLineCopy.array;

  try {
input.map!(s => (s.find!"a >= '0' && a <= '9'".front - '0') * 10 + s.retro.find!"a >= '0' && a <= '9'".front - '0')
         .sum.writefln!"Part1: %d";
  } catch (Error e) {
    writefln!"Part1: malformed input";
  }

auto words = "one, two, three, four, five, six, seven, eight, nine"
       .split(", ").zip(iota(1, 10))
.map!(x => tuple(x[0], x[0] ~ x[1].to!string ~ x[0])).array; input.map!(s => words.fold!((a, subst) => a.replace(subst[]))(s)) .map!(s => (s.find!"a >= '0' && a <= '9'".front - '0') * 10 + s.retro.find!"a >= '0' && a <= '9'".front - '0')
       .sum.writefln!"Part2: %d";
}
```

The key features are:
* I'm using `import std;` and this makes the source code smaller (at the expense of a bit longer compile time). This is a bad style in real applications, but suitable here. * I'm reading the input data from `stdin`, because it's a common convention for solving algorithmic puzzles on various websites (such as codeforces or atcoder). * The string "one, two, three, four, five, six, seven, eight, nine" was copy-pasted from the puzzle text and then parsed by the code. This was it's a bit faster to implement and less prone to typos. * For part2 the input text was preprocessed ("one" is replaced by "one1one", "two" is replaced by "two2two" and so on). And after such search & replace is complete, the whole task becomes the same as the already solved part1. Such approach makes the code slower, but the code is simpler and faster to implement. A useful tradeoff for the Advent of Code puzzles.

Reply via email to