Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

76 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Screenshot of most challenges solved

TypeScript Badge

Overview

Day Difficulty Solved Time Complexity Space Complexity
Day 1: Filter gift strings containing '#' Easy O(L) O(n)
Day 2: Make q total gifts from n object orders Easy O(n + q) O(n + q)
Day 3: Draw square gift perimeter Easy O(n^2) O(n^2)
Day 4: Decipher pin from cyphered tokens Medium O(L) O(L)
Day 5: Countdown Easy O(L) O(1)
Day 6: Matching gloves Easy O(n) O(k)
Day 7: Draw a custom tree Medium O(h^2) O(h^2)
Day 8: Find first non-repeating letter Easy O(n) O(n)
Day 9: Move robot Hard O(L + k) O(L + k)
Day 10: Depth Easy
Day 11: Unwatched gifts Easy
Day 12: Elf battle Medium
Day 13 Assembly board Medium
Day 14: Gift path Easy
Day 15: Draw table Medium
Day 16 Packing gifts Easy
Day 17: Consecutive lights Easy
Day 18: Consecutive lights II Medium
Day 19: Connecting flights Easy
Day 20: Vertical warehouse Easy
Day 21: Cleaning robot Medium
Day 22: Maze Hard O(n) O(n)
Day 23: Shortest distance Medium
Day 24: Mirror Trees Medium
Day 25: Small Lang Medium O(n + T) O(n)

Note on Space Complexity

Space complexity in this document means Auxiliary space, i.e. space reserved for the algorithm itself including the output, but without the input space itself.

Intro

I solved AdventJS 2025 coding challenge using TypeScript and Node.js for both runtime and tests.

Structure

Each day-XX-... directory contains both:

  • solution.ts
  • solution.test.ts

The tests are the biggest benefit you can take from this repo (apart from technical discussion) because they contain some of the 'official' input cases which I used them to validate my solution before submitting, and in case the online runner found edge cases my solution didn't handle, I added those case to the test suite and fixed the solution.

Install

You will need:

git clone https://github.com/new-AF/AdventJS-2025-challenge-solutions

cd AdventJS-2025-challenge-solutions

pnpm install

Running extended Small Lang, the last solution

pnpm day-25-small-language-extended

# outputs
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++!+++++++++++++++++++++++++++++!+++++++!!+++!-------------------------------------------------------------------------------!+++++++++++++++++++++++++++++++++++++++++++++++++++++++!++++++++++++++++++++++++!+++!------!--------!-------------------------------------------------------------------!
# Hello World!

Run Individual Tests

# pnpm day-xx-folder-...

pnpm day-8-non-repeating-letter

Run All Tests

pnpm test

Day 1: Filter gift strings containing '#'

The Challenge

Return a filtered out array of strings that don't contain character '#'

{
    input: ["car", "doll#arm", "ball", "#train"],
    expectedOutput: ["car", "ball"],
}

My Solution

Pretty straightforward:

  • we'll use .filter array method
  • provide a predicate function that will run on each string,
  • use the built-in .includes method to ensure the string does not contain '#'

Time complexity

O(L) where L is the total length of all strings provided. This is because in the worst-case we have to process every character of each string before concluding it does not contain the offending character.

In other words the work is proportional to the total length, if the total character count doubled, or tripled, so would at least the amount of work done.

Space complexity

O(n) because in the worst case, if no string contains the offending character, we're returning a entire new copy of the array.

Day 2: Make q total gifts from n object orders

The Challenge

Given an array of instruction objects, produce quantity copies for each string in toy value, and return the flattened array. Ignore objects with quantity <= 0

{
    input: [
        { toy: "car", quantity: 3 },
        { toy: "doll", quantity: 1 },
        { toy: "ball", quantity: 2 },
    ],

    expectedOutput: ["car", "car", "car", "doll", "ball", "ball"],
}

My Solution

Pretty straightforward too:

  • we'll .filter out objects with quantity <= 0
  • .map over each object, allocate a new nested array of length quantity
    • .fill it with toy value strings
  • call .flat on the outer array
  • return the flatten array.

Time complexity

O(n + q) where n is the count of all objects, and q is the sum of all quantities. This is broken as O(n) for total objects work, in addition to O(q) for all elements produced.

The work is proportional to both the objects count and how many strings to produce.

Space complexity

O(n + q) This is broken as O(n) for the temporary array holding references to the objects filtered, in addition O(q) for all elements produced.

Day 3: Draw square gift perimeter

The Challenge

Given a size length of a square, and a symbol, draw the square outer perimeter. Print inner cells as empty (space).

{
    size: 4,
    symbol: "*",
    expectedOutput: `
****
*  *
*  *
****`,
}

My Solution

  • Iterate size times,
  • depending on the index, if it's the first or last line:
    • draw either the top full symbol line, or
    • draw the mostly hollow middle line, with only 2 symbol on the outer perimeter.
  • .join the lines with \n and print the output.

Time complexity

O(n^2) because on each iteration, we do O(n) work, creating the n length line.

Space complexity

O(n^2) because we store n^2 cell elements of the square output.

Day 4: Decipher pin from cyphered tokens

The Challenge

Given a string of tokens (substrings), process them and output the digit for each token.

Each token resembles this format n_Ops1_Ops2_... (without the underscores) where

  • n is the initial digit to modify
  • Ops are instructions like
    • + to increment,
    • - to decrement,
    • < to return digit from previous token.
{
    input: "[1++][2-][3+][<]",
    expectedOutput: "3144"
}

My Solution

  • tokenize the string (with regular expressions) as ["1++", "2-", "3+", "<"]
  • keep a global previousDigit
  • iterate over each token,
  • apply decipher(...) to obtain the digit
  • .join the outputs

Time complexity

O(L) where L is the entire length of the input string, because we have to process each character and apply the deciphering logic.

Space complexity

O(L) because I store all the tokens, and other intermediate arrays.

The optimal solution (streaming parser) would be:

  • O(1) if the output size is constrained, as in this case to 4 fixed size slots,
  • O(n) if the input is unbounded, where n where n is the tokens count.

Day 5: Countdown

The Challenge

Return the seconds difference between two date-time strings. The caveat is the strings are in a non-standard format so need processing.

const takeoff = "2025*12*25@00|00|00 NP";

{
    input: "2025*12*24@23|59|30 NP",
    takeoff,
    expectedOutput: 30
}

My Solution

  • apply a fixed number of .replaceAll operations to convert the strings to standard format
    • e.g. 2025*12*24@23|59|30 NP to 2025-12-24T23:59:30Z
  • obtain Date() objects
  • subtract the dates, to obtain the milliseconds.
  • divide the result by 1000 and Math.floor it.

Time complexity

O(L) because replaceAll checks each character to convert all the non-standard symbols.

Space complexity

O(1) because we only need fixed space for the Date objects, and calculations.

Day 6: Matching gloves

The Challenge

Count the match pairs of glove objects that are identical in both color and hand direction. Preserve the order, as soon as a new pair is found list it, multiple pairs of the same color are allowed.

{
    input: [
        { hand: "L", color: "red" },
        { hand: "R", color: "red" },
        { hand: "R", color: "green" },
        { hand: "L", color: "blue" },
        { hand: "L", color: "green" },
    ],
    expectedOutput: ["red", "green"],
}

My Solution

  • use a hash map Map as quasi tally
  • .forEach over the input array
  • on the fist encounter of color, set it as key, and value as {left: 0, right:0} initially
  • later increment the left and right piece
  • as soon as either the left or right count is >=1 we found a new pair, push it, and decrement counts accordingly

Time complexity

O(n) where n is the number of objects, because we have to process each.

Space complexity

O(k) or O(n) where k is the number of distinct colors, because they are the keys of the hash map. In the worst case k = n because the whole input would be objects of unique colors but only one piece.

Day 7: Draw a custom tree

The Challenge

Draw a centered Christmas tree of height and with custom ornament that repeat every frequency

{
    height: 5,
    ornament: "o",
    frequency: 2,
    expectedOutput: `
    *
   o*o
  *o*o*
 o*o*o*o
*o*o*o*o*
    #
`,
}

My Solution

  • Iterate height times
  • generate the 2 * index + 1 inner array .fill it with *
  • iterate over all cells and mark those that are % frequency
  • center the tree by padding it as Math.floor((maxWidth - array.length) / 2)

Time complexity

O(h^2) where h is height. This is because the tree has h^2 + 1 elements, and this comes from math, the sum of the sequence that represents rows lengths 1, 3, 5, ..., 2 * height - 1 is h^2 In addition to the base element #

Space complexity

O(h^2) because we store at least the entire tree elements count, in addition to intermediary processing arrays.

Day 8: Find first non-repeating letter

screenshot of day 8 problem and my solution having passed

https://adventjs.dev/challenges/2025/8

The Challenge

Return the first non-repeating letter (regardless of casing) in a string. If all letters are repeated, the function should return an empty string. e.g.

  • "Gift" should return "G"
  • "sS" should return ""
  • "reindeeR" should return "i"

Rest of test cases in day-8-non-repeating-letter/solution.test.ts

My Solution

  1. Use a dictionary (JS Object {})

  2. Iterate over the string and mark if the lowercase letter occurred before.

    We have to run the entire length of the string, because the first non-repeating letter could be at the very end (e.g. "aaaaaaaaaaaab")

  3. Do another pass, and break out of the function at the first letter that is marked as having no duplicates by referencing the dictionary.

Time Complexity

Assuming the dictionary key insertion and retrieval is O(1) then:

findUniqueToy runs in O(n) or linear time, because:

  • Dictionary construction is O(n) because we iterate over the entire string, and do n queries and insertions.
  • O(n) for the final pass, doing n dictionary retrievals.

Space Complexity

Overall space complexity is O(n) because:

  • Dictionary size is O(1) or constant time due to fixed size of alphabet.

  • O(n) for extra array allocation const array = Array.from(toy);

    We could get rid of the extra allocation, and bring overall space complexity to O(1) but we would have to use a regular for loop instead of the forEach array method (because strings in JS don't have a native forEach)

    To me that's an acceptable tradeoff because I gain extra code readability: forEach explicitly states that we run the entire length of the string, and there's no early exit as would be possible with a traditional for loop.

Improvements

Instead of the ambiguous empty string ("") on failure, the function should always return an object:

{
    success: boolean;
    (optional) value: string;
}

This will explicitly tell if the string had any non-repeating letters. If all the letters are repeated success would be false, and we wouldn't return value

Day 9: Move robot

Screenshot of problem 9 solvedhero

The Challenge

Move the robot on the 2D board (nested array), using a separate input string as control. The board has the following element types:

  • @ is our robot
  • * is something to pick, return 'success' immediately.
  • # is obstacle , return 'crash' immediately, or when robot goes outside board.
  • . is an empty spot, exhaust input and return 'fail' if robot ends here.

Example:

1) Board
.....
.*#.*
.@...
.....
2) Control string
Input Expected Return
'D' (Down) 'fail' because robot ended on empty spot ('.'), having exhausted all input
'U' (Up) 'success' immediately, because the robot picked up picked up something ('*')
'RU' (Right, Up) 'crash' immediately, because the robot hit an obstacle ('#')

My Solution

  • Convert board from one giant string to a 2D nested array (string[][])

    Both Time and space complexity are O(L) where L is the length of the original string, or equivalenty O(n) where n is the count of cells on the board. The work done is proprtional to the number of cells on the board.

  • Find initial robot location, linear sweep. Time complexity is O(n) or equivalently O(L)

  • .map the ambiguous control characters ('U') into readable TypeScript enums (BoardMove.Up)

    Both Time and space complexity are O(k) where k is the length of the control string.

  • Follow control moves, and apply result logic.

    Time complexity is O(k) where k is the length of the control string. There is no loop detection because that would violate the problem description, so k is unbounded by n the number of cells.

Time complexity

O(n + k) or equivalently O(L + k) where n is the number of cells on the board, and L is the length of the original board represented as a string, k is the control string length.

The work is proportional to both the board size and control input string, and grows independently with respect to both.

Space complexity

O(n + k) or equivalently O(L + k) The is broken as:

  • O(n) to convert the original string board to a 2D nested array.

  • O(k) to convert the control string to a 1D array and .map the characters to enumns.

Had we traded off readability by not implementing those 2 steps and hence increased the likelihood of bugs in order to save on memory, then the Space complexity would be O(1)

Day 13: Assembly board

screenshot of my day 13 problem and my solution having passed

Challenge

Link: https://adventjs.dev/challenges/2025/13

type Factory = string[];
type Result = "completed" | "broken" | "loop";

export const runFactory = (factory: Factory): Result => {
    // ...
};

Input example

{
    factory: [
        ">v.",
        "^.."
    ],
    expectedOutput: "completed"
}

Move a gift using instructions (string[]) on a 2D assembly board, where each string is a series of instructions:

  • '>' move gift one step right on same row.
  • '<' move gift one step left on same row.
  • 'v' move gift one row down.
  • '^' move gift one row up.
  • '.' exit pod.

Return these outcomes, early if possible:

  • 'completed', if gift hits an exit spot (.)
  • 'loop', if gift returns to a previously visited position.
  • 'broken' if gift ends outside of assembly board.

Solution

day-13-assembly-board/solution.ts

  • Use a single while loop: get current the row, column position of the gift.

  • Detect loops: use a Set to check if we visited a previous position (row, column), and return 'loop' if need be.

  • Call the handler function for that instruction ( '>' ), it returns either:

    • 'completed' outcome, in which case return early or,
    • new position.
  • Check if new position is out of board bounds, and return 'broken'

  • Continue and process next instruction.

Code

/*

Day 13: Assembly board

Move a gift using instructions (`string[]`) on a **2D assembly board**, where each `string` is a series of instructions:

-   `'>'` move gift one step right on same row.
-   `'<'` move gift one step left on same row.
-   `'v'` move gift one row down.
-   `'^'` move gift one row up.
-   `'.'` exit pod.

Return these outcomes, early if possible:

-   `'completed'`, if gift hits an exit spot (`.`)
-   `'loop'`, if gift returns to a previously visited position.
-   `'broken'` if gift ends outside of assembly board.
*/

type Factory = string[];
type Result = "completed" | "broken" | "loop";

export const runFactory = (factory: Factory): Result => {
    type Instruction = ">" | "<" | "^" | "v" | ".";

    // assembly line outcome
    enum Outcome {
        Broken = "broken",
        Completed = "completed",
        Loop = "loop",
    }

    type Position = { row: number; column: number };

    type Transition = { outcome: Outcome } | Position;

    // visited locations key
    const makeKey = ({ row, column }: Position) => `${row}, ${column}`;

    // is next location out of bounds
    const isOutOfBounds = ({ width, height, row, column }) =>
        row < 0 || row >= height || column < 0 || column >= width;

    // returns either next coordinates, or assembly line outcome
    const instructionHandlers: Record<
        Instruction,
        (pos: Position) => Transition
    > = {
        ".": ({ row, column }) => {
            return { outcome: Outcome.Completed };
        },

        ">": ({ row, column }) => {
            // advance column
            return { row, column: column + 1 };
        },

        "<": ({ row, column }) => {
            // move back
            return { row, column: column - 1 };
        },

        v: ({ row, column }) => {
            // move down
            return { row: row + 1, column };
        },
        "^": ({ row, column }) => {
            // move up
            return { row: row - 1, column };
        },
    };

    // assembly line state
    const state: {
        row: number;
        column: number;
        visitedPositions: Set<string>;
    } = {
        row: 0,
        column: 0,
        visitedPositions: new Set(),
    };

    const boardInfo = {
        width: factory.length > 0 ? factory[0].length : 0,
        height: factory.length,
    };

    while (state.row < boardInfo.height) {
        const line = factory[state.row];
        const instruction = line[state.column];

        // current position
        const currentPosition: Position = {
            row: state.row,
            column: state.column,
        };

        // 1) detect loops (if we visited this previously)
        const key = makeKey(currentPosition);
        if (state.visitedPositions.has(key)) {
            return Outcome.Loop;
        }
        state.visitedPositions.add(key);

        // returns either next coordinates, or assembly line outcome
        const result = instructionHandlers[instruction](currentPosition);

        // 2) break early if success
        if ("outcome" in result) {
            return result.outcome;
        }

        // 3) are new coordinates out of bounds
        const nextPosition = result;

        if (
            isOutOfBounds({
                ...nextPosition,
                width: boardInfo.width,
                height: boardInfo.height,
            })
        ) {
            return Outcome.Broken;
        }

        state.row = nextPosition.row;
        state.column = nextPosition.column;
    }

    // if factory is empty
    return Outcome.Broken;
};

Time complexity

Is linear O(n) with respect to n = count of instructions. If instructions doubled so would run time.

Space complexity

Is also linear linear O(n) because of the Set<Position> we use to detect loops. At most we'd store n positions, i.e. row, column of each instruction result.

Example, classic loop

We would have store entire input length (4) before we can tell this is a loop.

{
    // classic loop
    factory: `
>v
^<
`,
    expectedOutput: "loop",
}

Tests

day-13-assembly-board/solution.test.ts

Note

runFactory takes in string[], where each string contains instructions for that specific row, but this format although easy for the algorithm to digest, makes it hard to visualize the 2D board.

So I made tests input a single multi-line string, that gets converted (split) into string[] before being fed to runFactory.

Example:

{
    // classic loop
    factory: `
>v
^<
`,
    expectedOutput: "loop",
}

Gets converted to below:

{
    // classic loop
    factory: [
">v",
"^<"
],
    expectedOutput: "loop",
}

Day 25: Small Lang

Screenshot of Small Lang printing Hello World

The Challenge

Build a single counter machine, which consumes an input string (encoded program), and returns the value of the single counter. Each character in the input string is an instruction as following:

  • ">" is effectively the keyword continue in programming languages, it does nothing but but advance to the next character/instruction. -"+": Increments the single counter,
  • "+": Increments the single counter value, and moves onto the next instruction,
  • "-": Decrement the single counter value, and moves onto the next instruction,
  • "[": Loop Start, marks the beginning of loop, you can think of it as a simplified while which operates as following:
    • If the single counter is 0 (effectively false) it jumps to the end of the loop ("]") and onto the instruction after.
    • If the single counter is not zero, it enters the loops and executes the instructions contained there.
      • For example "--[++] enters the loops when the counter is -2 and loops incrementing until it's 0.
      • Be careful though, the input program can continue infinite loops, as in the case of real world programs, but this is not your problem anymore.
  • "]": Loop End, at this point, you need to check the single counter value-
    • If it is 0, you end looping and move onto the next instruction.
    • If it not zero, you jump back to "[", continue looping, and so forth.
  • "{": Condition Check Start, effectively an if statement:
    • If the single counter is 0 this means false and you jump to the end of the condition "}"
    • If it is not zero, you enter the code block and execute the instructions contained there.
      • For example: "+{---}" returns -2 because you entered when the value is 1 and ran the instructions contained there.
  • "}": Condition Check End, you don't do anything here and move onto the next instruction.

    There is no jumping back, or looping inherent into the condition itself, it executes 0 or 1 times.

For example:

[
    { input: "+++", expectedOutput: 3 },
    { input: "+--", expectedOutput: -1 },
    { input: ">+++[-]", expectedOutput: 0 },
    { input: ">>>+{++}", expectedOutput: 3 },
    { input: "+{[-]+}+", expectedOutput: 2 },
    { input: "{+}{+}{+}", expectedOutput: 0 },
    { input: "------[+]++", expectedOutput: 2 },
    { input: "-[++{-}]+{++++}", expectedOutput: 5 },
    { input: "-[+{+}]+", expectedOutput: 1 },
    { input: "[{}]", expectedOutput: 0 },
];

My Solution

While similar to BrainF---, Small Lang is different because it is not Turing-complete, while BF is.

Turing completeness meaning you can program arbitrary functions like the Fibonacci sequence, and for that feature you need at least 2 counters, but we only have 1. But this doesn't mean we can't do some useful things like we'll show later.

The solution consists of 2 passes:

  1. Building the Jump Table this enables looping and conditional checks.
  2. The main while running the program through the State Functions.
  • We model our machine as a simple state object that contains the current reading head index, and the single value counter (that we return later.):

    // our machine state
    type State = {
        tapeIndex: number;
        value: number;
    };
    
    let currentState: State = {
        tapeIndex: 0,
        value: 0,
    };

    tapeIndex alone determines how the machine operates.

  • For each of the token types, we define a corresponding function that takes 1) the current state of the machine, 2) the Jump Table, returns the new state, containing the new read index and the single value counter:

    // produce our next state
    type StateFunction = (state: State, globalJumpTable: JumpTable) => State;
    
    // handling looping, check if value is 0, jump to end of loop, otherwise advance
    (currentState: State, passedJumpTable: JumpTable): State => {
        const { value, tapeIndex } = currentState;
    
        // jump to end of loop
        if (value === 0) {
            // malformed input
            if (!passedJumpTable.has(tapeIndex)) {
                raiseMalformedInput();
            }
    
            const loopEnd = passedJumpTable.get(tapeIndex);
            const nextIndex = loopEnd.index;
    
            return { value, tapeIndex: nextIndex };
        }
    
        // else enter the loop, move to next instruction
        return { value, tapeIndex: tapeIndex + 1 };
    };
  • We run a simple while as long as there are tokens available, feed then into the state function, and update the state:

    // run the program the program, as long as there are instructions
    while (currentState.tapeIndex < code.length) {
        const { type, _ } = allTokens[currentState.tapeIndex];
        const transform = tokenTypeToStateFunction[type];
        const nextState = transform(currentState, globalJumpTable);
        currentState = nextState;
    }
    
    // return final value
    return currentState.value;

Pass 1: Building the Jump Table

  • We use a Stack to handle arbitrarily nesting of loops and conditions, e.g.:

    {
        input: "+{[-]+}+",
        expectedOutput: 2
    }
  • We iterate over the now tokens array Tokens[] and as soon we encounter the opening token: either TokenType.Loop_Start or TokenType.If_Start we push them onto the stack. The Token also contains the index so this will be handy later.

  • We continue iterating, we continue iterating and as soon we find the closing token: TokenType.Loop_End or TokenType.If_End we pop the last token:

    • To avoid processing malformed inputs like "{]", We inspect the popped token to ensure it mirrors the current token.

    • If the tokens mirror each other, we insert them into the table. e.g.:

    // in case we need to skip over the loop; jump[start] = end
    globalJumpTable.set(loopStart.index, token);
    
    // in case we need to loop back; jump[end] = start
    globalJumpTable.set(index, loopStart);

    Both Time and Spce complexity for building the Jump Table is O(n/2) or O(n) because the most insertions we do is n/2 because in the worst case of well formed input e.g. {{}} we'll processing half the tokens array.

Pass 2: The main while loop

We have shown the main loop before, it doesn't have any indexing manipulation logic, it relies one the state function to do that, and it runs as long as the tapeIndex is within bounds, which means it can go forward or backward, and also run indefinitely if the program is encodes an infinite loop:

// run the program the program, as long as there are instructions
while (currentState.tapeIndex < code.length) {
    const { type, _ } = allTokens[currentState.tapeIndex];
    const transform = tokenTypeToStateFunction[type];
    const nextState = transform(currentState, globalJumpTable);
    currentState = nextState;
}

// return final value
return currentState.value;

The time complexity is O(T) where T is the total number of instructions executed encoded within the program itself, not the number of tokens of the static program.

Time complexity

O(n + T) where n is the number of tokens of the static program (size of the program), while T is the number of instructions encoded in the program itself.

O(T) describes the work done by our machine which directly reflects the behavior of the encoded program itself, If the program encodes a linear algorithm, our machine will run in linear time, if the encoded algorithm is exponential our machine will take exponential time to complete, If the program encodes an infinite loop, our machine will never halt.

In short our solution O(n + T) reflects 1) the work done by building the machine O(n) including constructing the Jump Table, and 2) O(T) the cost of running the machine which is entirely determined by the growth behavior of the encoded program itself. Our solution grows independently with respect to both variables.

Space complexity

O(n) where n is the number of tokens in the static program, or size of the program, and this accounts for:

  • O(n) the size of the array used to convert the the string characters to Tokens
  • O(n) the size of the Jump Table
  • O(n) the size of the stack used to construct the Jump Table

Extending the language to print stuff

Because how we structured the solution, as series of State Functions it's easy to add a printing functionality.

We will designate the character "!" to print the single counter as ASCII character.

The State Function is the first one to have a side-effect as it will print the ASCII character to the console, and advance the character.

Printing "Hello World!"

pnpm day-25-small-language-extended
Output

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++!+++++++++++++++++++++++++++++!+++++++!!+++!-------------------------------------------------------------------------------!+++++++++++++++++++++++++++++++++++++++++++++++++++++++!++++++++++++++++++++++++!+++!------!--------!-------------------------------------------------------------------!

Hello World!

This is broken as the joined string of the individual characters

[
    // H=72
    "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++!",
    //  +29; e=101
    "+++++++++++++++++++++++++++++!",
    // +7; l=108
    "+++++++!",
    // l=108 again
    "!",
    // +3; o=111
    "+++!",
    // -79; space=32
    "-------------------------------------------------------------------------------!",
    // +55; W=87
    "+++++++++++++++++++++++++++++++++++++++++++++++++++++++!",
    // +24; o=111
    "++++++++++++++++++++++++!",
    // +3; r=114
    "+++!",
    // -6; l=108
    "------!",
    // -8; d=100
    "--------!",
    // -67; !=33
    "-------------------------------------------------------------------!",
];

About

My TypeScript solutions to the AdventJS 2025 coding challenge

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages