elation

data fizz Fizz
data buzz Buzz
concat fizz buzz fizzbuzz
data zero 0
data one 1
data three 3
data five 5
data i 1
data max 100
label loop
compare i > max loop_over
jump_if loop_over end
calculate i % three remainder1
compare remainder1 == zero three_divisible
calculate i % five remainder2
compare remainder2 == zero five_divisible
compare three_divisible && five_divisible both_divisible
jump_if both_divisible fizzbuzz
jump_if three_divisible fizz
jump_if five_divisible buzz
print i
calculate i + one i
jump loop
label fizzbuzz
print fizzbuzz
calculate i + one i
jump loop
label fizz
print fizz
calculate i + one i
jump loop
label buzz
print buzz
calculate i + one i
jump loop
label end
exit

arson: lang around fire

prepmatch printGrid(grid) {
    for i through (0, grid[.length]) {
        burn row = grid[i]
        burn rowStr = ""
        for j through (0, row[.length]) {
            burn num = row[j]
            burn rowStr = rowStr + str(int(num)) + " " 
        }
        fire(rowStr)
    }
    fire()
}

fire("Sudoku grid unsolved:")
printGrid(sudokuGrid)
if (solve(sudokuGrid)) {
	fire("Sudoku grid solved:")
	printGrid(sudokuGrid)
} else {
	fire("No solution found.")
}

prepmatch usedRow(grid, row, num) {
    for i through (0, grid[row][.length]) {
        burn curr = grid[row][i]
        if (curr == num) {
            return True
        }
    }
    return False
}

prepmatch usedColumn(grid, column, num) {
    for i through (0, grid[.length]) {
        burn row = grid[i]
        if (row[column] == num) {
            return True
        }
    }
    return False
}

prepmatch usedBox(grid, startingRow, startingColumn, num) {
    for i through (startingRow, startingRow + 3) {
        for j through (startingColumn, startingColumn + 3) {
            if (grid[i][j] == num) {
                return True
            }
        }
    }
    return False
}

prepmatch isSafe(grid, row, column, num) {
    burn rowUsed = usedRow(grid, row, num)
    burn columnUsed = usedColumn(grid, column, num)
    burn boxUsed = usedBox(grid, row - row % 3, column - column % 3, num)
    if ((rowUsed == False) and (columnUsed == False) and (boxUsed == False)) {
        return True
    }
    return False
}

prepmatch emptySquare(grid) {
    for i through (0, grid[.length]) {
        for j through (0, grid[i][.length]) {
            if (grid[i][j] == 0) {
                return [i, j]
            }
        }
    }
    return False
}

prepmatch solve(grid) {
	# The heart of the code - this is a recursive function
	if (emptySquare(grid) == False) {
		# If there are no more empty squares
		return True
	}
	burn pos = emptySquare(grid)
	burn row = pos[0]
	burn col = pos[1]
	for num through (1, 10) {
		# Test all numbers 1 - 9
		if (isSafe(grid, row, col, num)) {
			grid[row][.update](col, num)
			if (solve(grid)) {
				# Recursively run solve() again; if the final result returns True, then grid has been solved
				return True
			}
			grid[row][.update](col, 0) # Otherwise, we need to backtrack - we're still in the original function, so we reset it back to 0
		}
	}
	return False
}

easel: lang around painting

prepare rows as 64
prepare cols as 64
prepare dbg as true

brush Cell has { x, y, live }

~ Exercise: try setting a custom pattern instead of randomness!
sketch seed {
  prepare cells as []
  loop x through (0, rows) {
    loop y through (0, cols) {
      prepare live as false
      prepare chance as random(0, 100)
      if (chance < 10) {
        prepare live as true
      }
      cells.add(prep Cell(x: x, y: y, live: live))
    }
  }
  finished cells
}

prepare cells as seed()

sketch getNeighbors needs (cells, index) {
  ~ Get neighbors around a cell
  prepare neighbors as []

  ~ Populate neighbors
  if (index - rows - 1 > 0) {
    neighbors.add(cells[index - rows - 1])
  }
  if (index - rows > 0) {
    neighbors.add(cells[index - rows])
  }
  if (index - rows + 1 > 0) {
    neighbors.add(cells[index - rows + 1])
  }
  if (index > 0) {
    neighbors.add(cells[index - 1])
  }
  if (index < cells.length - 1) {
    neighbors.add(cells[index + 1])
  }
  if (index + rows - 1 < cells.length - 1) {
    neighbors.add(cells[index + rows - 1])
  }
  if (index + rows < cells.length - 1) {
    neighbors.add(cells[index + rows])
  }
  if (index + rows + 1 < cells.length - 1) {
    neighbors.add(cells[index + rows + 1])
  }

  prepare alive as []
  loop i through (0, neighbors.length) {
    if (neighbors[i].live) {
      alive.add(neighbors[i])
    }
  }
  finished alive
}

if (dbg) {
  ink(getNeighbors(cells, rows * cols / 2))
}

sketch painting {
  ~ This loop runs every iteration and must be in every program
  loop i through (0, cells.length) {
    prepare cell as cells[i]
    prepare neighbors as getNeighbors(cells, i)
    if (cell.live) {
      if (neighbors.length < 2 || neighbors.length > 3) {
        ~ Any live cell with fewer than two neighbors dies, as if by underpopulation
        ~ Any live cell with more than three live neighbors dies, as if by overpopulation
        prepare cell.live as false
      } elif (!(cell.live && neighbors.length == 3)) {
        ~ Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction
        prepare cell.live as true
      }
    } else {
      if (neighbors.length == 3) {
        ~ Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction
        prepare cell.live as true
      }
    }
    
    if (cell.live) {
      ~ Now draw the cell if it's alive!
      prepare color as prep Color(r: 0, g: 255, b: 0)
      Canvas.fill(cell.x, cell.y, color)
    } else {
      ~ If it's dead, turn the cell off
      Canvas.erase(cell.x, cell.y)
    }
  }
}

if (dbg) {
  sketch includes needs (array, value) {
    loop i through (0, array.length) {
      if (array[i] == value) {
        finished true
      }
    }
    
    finished false
  }

  prepare test as ["hello", "world", "fox"]
  ink(test)

  if (!(false && includes(test, "foxes"))) {
    ink("NOT false AND includes foxes in test evaluates to true")
  }

  painting()
}

and meet some of the biggest programming lang creators

What's the craziest syntax you can think of? Features? Here are some ideas.

Plus, we'll have the coolest speakers. And if you win, you'll get a signed copy of Crafting Interpreters.

Jared Sumner, behind Bun

To be determined!

Here's what a week of hacking could look like.

*Once the event begins, we'll send you a calendar invite with all the up to date info.

Interval
Sat
Sun
Mon
Tue
Wed
Thu
Fri
Sat
12AM
Hack away!
Hack away!
Hack away!
Hack away!
Hack away!
Hack away!
Hack away!
1AM
2AM
3AM
4AM
5AM
6AM
7AM
8AM
9AM
10AM
11AM
Final prep!
12PM
Hacking begins!
Final submissions
1PM
Hack away!
2PM
3PM
4PM
Error handling in langs
How do JIT compilers work?
5PM
6PM
7PM
AMA with Jarred Sumner
Demo night - share what you're working on!
Hack night - hack and debug together!
AMA with Andrew Kelley
Share what you're working on!
AMA with Bob Nystrom
Feedback night - throw ideas!
8PM
Announce winners!
9PM
10PM
11PM

Rules

  • You must be a high schooler
  • You can work in teams of up to three!
  • Submissions for this jam can only be worked on between June 08, 2024 at 12PM EST and June 29, 2024 at 12PM EST.
  • All programming languages must meet the following criteria:
    • Minimally, should have the following features: variables, looping (think: for/while loops, not explicit recursion), conditional branching (think: if/else statements), and some form of recursion (think: functions).
    • Cannot use a third party tool, e.g. a parser generator.
    • Must be open source.
    • Must include a demo and three functional example programs.

Rating

Your fellow hackers will vote on what programming languages do the following the most well:

  • Uniqueness: How unique is the idea? Idea wise, are there similar programming languages out there?
  • Technicality: How technically difficult is the implementation? Bonus points given for giving a walkthrough of the implementation for your programming language during one of our demo nights.
  • Helpfulness: Were you helpful to other people in the community? Did other people learn new things from you? Did you share new things that you learned?

Prizes

The top three will get the following:

  • Signed copy of Crafting Interpreters by speakers
  • Retweet by Hack Club

Anyone that ships a programming language will get the following:

  • A copy of Crafting Interpreters
  • langjam sticker pack!