Remove my-solutions, which were only included because of typo
This commit is contained in:
parent
2a1b6cfe2d
commit
ba659ddd97
|
@ -1,4 +1,4 @@
|
|||
config/.env
|
||||
my_solutions/
|
||||
/my-solutions
|
||||
puzzles.toml
|
||||
*.sqlite3*
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "active_support/all"
|
||||
require "pry"
|
||||
|
||||
class Set
|
||||
alias :includes? :include?
|
||||
end
|
||||
|
||||
class State
|
||||
def initialize(flat)
|
||||
@flat = flat
|
||||
end
|
||||
|
||||
attr_reader :flat
|
||||
|
||||
def square
|
||||
@square ||= @flat.in_groups_of 4
|
||||
end
|
||||
|
||||
# Return the index of the empty square, 0-15
|
||||
def empty
|
||||
@empty ||= flat.index 0
|
||||
end
|
||||
|
||||
def slide(dir)
|
||||
# Let's assume the move is possible
|
||||
if dir == :up
|
||||
# index of the tile to move, so that's the tile below the current pos
|
||||
# So we're going to grab empty and add three to push it to the next row
|
||||
# And that's all good as long as this is a valid move
|
||||
to_move_index = empty + 4
|
||||
elsif dir == :down
|
||||
to_move_index = empty - 4
|
||||
elsif dir == :left
|
||||
# Only valid if empty is in the first three columns
|
||||
# So the index + 1 should work
|
||||
to_move_index = empty + 1
|
||||
elsif dir == :right
|
||||
to_move_index = empty - 1
|
||||
end
|
||||
|
||||
new_state = flat.dup
|
||||
|
||||
to_move = flat[to_move_index]
|
||||
|
||||
new_state[empty] = to_move
|
||||
new_state[to_move_index] = 0
|
||||
|
||||
return State.new new_state
|
||||
end
|
||||
|
||||
def possible_moves
|
||||
valid = []
|
||||
if empty < 12 # so 0 - 11, that is, the first three rows
|
||||
valid.push :up
|
||||
end
|
||||
if empty >= 4
|
||||
valid.push :down
|
||||
end
|
||||
# Can't go left if empty is in the last row
|
||||
if empty % 4 != 3
|
||||
valid.push :left
|
||||
end
|
||||
if empty % 4 != 0
|
||||
valid.push :right
|
||||
end
|
||||
|
||||
return valid
|
||||
end
|
||||
|
||||
def adjacent_states
|
||||
return possible_moves.map do |dir|
|
||||
slide dir
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
@s ||= flat.join ""
|
||||
end
|
||||
|
||||
def dis
|
||||
puts square.map(&:to_s).join("\n").sub("0", " ")
|
||||
puts "\n"
|
||||
end
|
||||
end
|
||||
|
||||
seen_states = Set.new
|
||||
|
||||
# Last is actually the one we're going to work off of, so we can push and pop
|
||||
unchecked_states = [State.new((0..15).to_a)]
|
||||
|
||||
while unchecked_states.length > 0
|
||||
state = unchecked_states.pop
|
||||
|
||||
state.adjacent_states.each do |s|
|
||||
unless seen_states.includes? s.to_s
|
||||
seen_states.add s.to_s
|
||||
unchecked_states.push s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# seen_states.count
|
||||
# => 181440
|
||||
|
||||
binding.pry
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
// From /Users/matthias/Programs/tmp-name-js-plus/main.js
|
||||
Object.defineProperty(Array.prototype, "chunks", {
|
||||
value: function chunks (chunkSize) {
|
||||
// TODO: Error on float
|
||||
if (chunkSize<= 0) {
|
||||
throw new Error("Window size must be a positive integer.");
|
||||
}
|
||||
|
||||
if (this.length < chunkSize) {
|
||||
return this.slice(0);
|
||||
}
|
||||
|
||||
const accum = [];
|
||||
for (let i = 0; i < this.length; i += chunkSize) {
|
||||
accum.push(this.slice(i, i + chunkSize));
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
});
|
||||
|
||||
const input = "W 3 N 5 I 2 W 3 E 2 R 5 O 1 I 5 S 2 S 8 O 2 I 8 W 5 W 6 W 2 W 1 E 7 O 9";
|
||||
|
||||
const i = input.split(" ").chunks(2)
|
||||
let x = 0, y = 0, z = 0;
|
||||
for (let [dir, dist] of i) {
|
||||
dist = parseInt(dist, 10);
|
||||
|
||||
if (dir === "N") {
|
||||
y -= dist;
|
||||
} else if (dir === "S") {
|
||||
y += dist;
|
||||
} else if (dir === "E") {
|
||||
x += dist;
|
||||
} else if (dir === "W") {
|
||||
x -= dist;
|
||||
} else if (dir === "I") {
|
||||
z += dist;
|
||||
} else if (dir === "O") {
|
||||
z -= dist;
|
||||
}
|
||||
}
|
||||
console.log(`(${x}, ${y}, ${z})`)
|
|
@ -1,108 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "active_support/all"
|
||||
require "pry"
|
||||
|
||||
class Set
|
||||
alias :includes? :include?
|
||||
end
|
||||
|
||||
class State
|
||||
def initialize(flat)
|
||||
@flat = flat
|
||||
end
|
||||
|
||||
attr_reader :flat
|
||||
|
||||
def square
|
||||
@square ||= @flat.in_groups_of 3
|
||||
end
|
||||
|
||||
# Return the index of the empty square, 0-8
|
||||
def empty
|
||||
@empty ||= flat.index 0
|
||||
end
|
||||
|
||||
def slide(dir)
|
||||
# Let's assume the move is possible
|
||||
if dir == :up
|
||||
# index of the tile to move, so that's the tile below the current pos
|
||||
# So we're going to grab empty and add three to push it to the next row
|
||||
# And that's all good as long as this is a valid move
|
||||
to_move_index = empty + 3
|
||||
elsif dir == :down
|
||||
to_move_index = empty - 3
|
||||
elsif dir == :left
|
||||
# Only valid if empty is in the first two columns
|
||||
# So the index + 1 should work
|
||||
to_move_index = empty + 1
|
||||
elsif dir == :right
|
||||
to_move_index = empty - 1
|
||||
end
|
||||
|
||||
new_state = flat.dup
|
||||
|
||||
to_move = flat[to_move_index]
|
||||
|
||||
new_state[empty] = to_move
|
||||
new_state[to_move_index] = 0
|
||||
|
||||
return State.new new_state
|
||||
end
|
||||
|
||||
def possible_moves
|
||||
valid = []
|
||||
if empty <= 5
|
||||
valid.push :up
|
||||
end
|
||||
if empty >= 3
|
||||
valid.push :down
|
||||
end
|
||||
# Can't go left if empty is in the last row
|
||||
if empty % 3 != 2
|
||||
valid.push :left
|
||||
end
|
||||
if empty % 3 != 0
|
||||
valid.push :right
|
||||
end
|
||||
|
||||
return valid
|
||||
end
|
||||
|
||||
def adjacent_states
|
||||
return possible_moves.map do |dir|
|
||||
slide dir
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
@s ||= flat.join ""
|
||||
end
|
||||
|
||||
def dis
|
||||
puts square.map(&:to_s).join("\n").sub("0", " ")
|
||||
puts "\n"
|
||||
end
|
||||
end
|
||||
|
||||
seen_states = Set.new
|
||||
|
||||
# Last is actually the one we're going to work off of, so we can push and pop
|
||||
unchecked_states = [State.new((0..8).to_a)]
|
||||
|
||||
while unchecked_states.length > 0
|
||||
state = unchecked_states.pop
|
||||
|
||||
state.adjacent_states.each do |s|
|
||||
unless seen_states.includes? s.to_s
|
||||
seen_states.add s.to_s
|
||||
unchecked_states.push s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# seen_states.count
|
||||
# => 181440
|
||||
|
||||
binding.pry
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 7.3 MiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 28 KiB |
|
@ -1,18 +0,0 @@
|
|||
require "active_support/all"
|
||||
|
||||
first_sundays = 0
|
||||
|
||||
start_date = Date.parse "1901-01-01"
|
||||
end_date = Date.parse "2000-12-31"
|
||||
|
||||
date = start_date
|
||||
|
||||
while date < end_date
|
||||
if date.day == 1 and date.sunday? then
|
||||
first_sundays += 1
|
||||
end
|
||||
|
||||
date = date.tomorrow
|
||||
end
|
||||
|
||||
p first_sundays
|
|
@ -1,15 +0,0 @@
|
|||
require "vips"
|
||||
|
||||
im = Vips::Image.new_from_file "Linoleum.jpg"
|
||||
|
||||
binding.irb
|
||||
|
||||
count = 0
|
||||
im.to_a.each do |row|
|
||||
row.each do |pixel|
|
||||
count += 1 if pixel == [52, 49, 53]
|
||||
# p pixel if pixel[0] == 71
|
||||
end
|
||||
end
|
||||
|
||||
p count
|
|
@ -1,208 +0,0 @@
|
|||
# Authored 2023 Matthias Portzel. Public Domain
|
||||
|
||||
require "pry"
|
||||
require "active_support/all"
|
||||
require "ostruct"
|
||||
|
||||
class Direction
|
||||
attr_accessor :name
|
||||
attr_accessor :offset
|
||||
|
||||
def initialize(name, offset)
|
||||
@name = name
|
||||
@offset = OpenStruct.new x: offset[0], y: offset[1]
|
||||
end
|
||||
end
|
||||
|
||||
DIRECTIONS = [
|
||||
Direction.new(:up_left, [-1, -1]),
|
||||
Direction.new(:up, [0, -1]),
|
||||
Direction.new(:up_right, [1, -1]),
|
||||
Direction.new(:left, [-1, 0]),
|
||||
Direction.new(:right, [1, 0]),
|
||||
Direction.new(:down_left, [-1, +1]),
|
||||
Direction.new(:down, [0, +1]),
|
||||
Direction.new(:down_right, [+1, +1])
|
||||
]
|
||||
|
||||
def for_xy (x_range, y_range, &block)
|
||||
for x in x_range
|
||||
for y in y_range
|
||||
block.call x, y
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Cell
|
||||
attr_accessor :is_alive
|
||||
def alive?
|
||||
@is_alive
|
||||
end
|
||||
def dead?
|
||||
!@is_alive
|
||||
end
|
||||
|
||||
for d in DIRECTIONS
|
||||
attr_accessor d.name
|
||||
end
|
||||
|
||||
attr_accessor :coords
|
||||
|
||||
def initialize(is_alive)
|
||||
@is_alive = is_alive
|
||||
@coords = OpenStruct.new x: nil, y: nil
|
||||
end
|
||||
|
||||
def neighbors
|
||||
DIRECTIONS.map do |d|
|
||||
send d.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class MobiusStrip
|
||||
# 2D array of trues and falses
|
||||
def initialize(grid)
|
||||
@state = grid.map do |row|
|
||||
row.map do |cell|
|
||||
Cell.new cell
|
||||
end
|
||||
end
|
||||
|
||||
max_x = @state.first.length
|
||||
max_y = @state.length
|
||||
|
||||
for_xy (0..(max_x-1)), (0..(max_y-1)) do |x, y|
|
||||
cell = @state[y][x]
|
||||
cell.coords.x = x
|
||||
cell.coords.y = y
|
||||
for d in DIRECTIONS
|
||||
link_x = (x + d.offset.x) % max_x
|
||||
link_y = (y + d.offset.y) % max_y
|
||||
if x + d.offset.x == -1 || x + d.offset.x == max_x
|
||||
link_y = ((max_y - 1) - link_y) % max_y
|
||||
end
|
||||
|
||||
cell.send(d.name.to_s + "=", @state[link_y][link_x])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def grid
|
||||
@state
|
||||
end
|
||||
|
||||
def self.from_string(grid_string)
|
||||
new(grid_string.split("\n").map(&:strip).map do |row|
|
||||
row.split("").map do |cell|
|
||||
cell == "#"
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def count_living_neighbors(cell)
|
||||
cell.neighbors.filter(&:alive?).length
|
||||
end
|
||||
|
||||
def step
|
||||
max_x = @state.first.length
|
||||
max_y = @state.length
|
||||
|
||||
new_grid = Array.new(max_y).map { Array.new(max_x) }
|
||||
for_xy (0..(max_x-1)), (0..(max_y-1)) do |x, y|
|
||||
cell = @state[y][x]
|
||||
live_neighbors = count_living_neighbors(@state[y][x])
|
||||
|
||||
# Cell alive, and 0..1 live neighbors, die
|
||||
# Cell alive, 4.. live neighbors, die
|
||||
# Cell alive, no change
|
||||
# Cell dead, 3 live neighbors, live
|
||||
# Cell dead, no change
|
||||
new_state = if cell.alive? && (0..1) === live_neighbors then
|
||||
false
|
||||
elsif cell.alive? && live_neighbors >= 4 then
|
||||
false
|
||||
elsif cell.alive? then
|
||||
true
|
||||
elsif cell.dead? && live_neighbors == 3 then
|
||||
true
|
||||
elsif cell.dead?
|
||||
false
|
||||
end
|
||||
|
||||
# p [cell.coords, cell.alive?.to_s, live_neighbors.to_s, new_state.to_s].join ", "
|
||||
|
||||
new_grid[y][x] = new_state
|
||||
end
|
||||
|
||||
MobiusStrip.new new_grid
|
||||
end
|
||||
|
||||
def display
|
||||
lines = @state.map do |row|
|
||||
chars = row.map do |cell|
|
||||
if cell.alive? then "#" else "." end
|
||||
end
|
||||
chars.join ""
|
||||
end
|
||||
lines.join "\n"
|
||||
end
|
||||
end
|
||||
|
||||
test_board = MobiusStrip.from_string(<<-EOF
|
||||
..........
|
||||
..........
|
||||
........#.
|
||||
........#.
|
||||
#.#..#..#.
|
||||
#.#.#.#...
|
||||
.##..##.#.
|
||||
..#.......
|
||||
##........
|
||||
..........
|
||||
EOF
|
||||
)
|
||||
|
||||
board = MobiusStrip.from_string(<<-EOF
|
||||
....................
|
||||
............###.....
|
||||
.....#.#...#...#....
|
||||
...........#........
|
||||
.....#.#...#........
|
||||
......#....#.###....
|
||||
...........#...#....
|
||||
...##......#...#....
|
||||
...##.......###.....
|
||||
....................
|
||||
....................
|
||||
...#####...#...#....
|
||||
...#.......#...#....
|
||||
...#.......#...#....
|
||||
...#####...#####....
|
||||
...#.......#...#....
|
||||
...#.......#...#....
|
||||
...#.......#...#....
|
||||
...#.......#...#....
|
||||
....................
|
||||
EOF
|
||||
)
|
||||
|
||||
# board = test_board
|
||||
past_boards = []
|
||||
day = 0
|
||||
loop do
|
||||
board_string = board.display
|
||||
|
||||
if past_boards.include? board_string
|
||||
after_days = day - 1
|
||||
puts "Repetition after day #{after_days}"
|
||||
break
|
||||
end
|
||||
|
||||
puts "On day #{day}:"
|
||||
puts board_string
|
||||
|
||||
past_boards << board_string
|
||||
board = board.step
|
||||
day += 1
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
const a = {b: 2, c: 3};
|
||||
|
||||
Object.defineProperty(Object.prototype, "with_key_methods", {
|
||||
value: function () {
|
||||
for (const {k: v} in this) {
|
||||
console.log(k, v);
|
||||
// this[k] = () => v;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
a.with_key_methods().b()
|
|
@ -1 +0,0 @@
|
|||
{"type":"module"}
|
|
@ -1,37 +0,0 @@
|
|||
// What is the second smallest prime number:
|
||||
// * whose digits are all odd,
|
||||
// * greater than 1057
|
||||
// * whose palindrome is also an odd number
|
||||
|
||||
const primes = [];
|
||||
|
||||
function isPrime(num) {
|
||||
if (primes.includes(num)) {
|
||||
return true;
|
||||
}else {
|
||||
const s = sqrt(num);
|
||||
for (const i = 0; i < s; i++) {
|
||||
if (num % i === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
primes.push(num);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Number.prototype.digits = function () {
|
||||
return this.toString().split().reverse().map(d => parseInt(d, 10));
|
||||
}
|
||||
|
||||
Number.prototype.isOdd = function () {
|
||||
return this % 2 === 1;
|
||||
}
|
||||
|
||||
const numFound = 0;
|
||||
for (const i = 1057; numFound < 2; i++) {
|
||||
|
||||
if (isPrime(i) && i.digits().all()) {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
require 'prime'
|
||||
|
||||
# // What is the second smallest prime number:
|
||||
# // * whose digits are all odd,
|
||||
# // * greater than 1057
|
||||
# // * whose palindrome is also an odd number
|
||||
|
||||
numFound = 0
|
||||
i = 1057
|
||||
while numFound < 30 do
|
||||
if i.prime? && i.digits.join.to_i.prime?
|
||||
p i
|
||||
numFound += 1
|
||||
end
|
||||
|
||||
i += 1
|
||||
end
|
|
@ -1,182 +0,0 @@
|
|||
// Going to regret doing this in JS but whatever
|
||||
|
||||
import "/Users/matthias/Programs/tmp-name-js-plus/main.js"
|
||||
|
||||
/*
|
||||
const points = [];
|
||||
for (let i = 0; i < 33; i++) {
|
||||
points.push({
|
||||
x: Math.floor(Math.random() * 100),
|
||||
y: Math.floor(Math.random() * 100)
|
||||
});
|
||||
}
|
||||
const seen = new Set();
|
||||
for (const point of points) {
|
||||
seen.add(JSON.stringify(point));
|
||||
}
|
||||
points.clear();
|
||||
for (const point of seen) {
|
||||
points.push(JSON.parse(point));
|
||||
}
|
||||
*/
|
||||
const points = [
|
||||
{ x: 21, y: 21 }, { x: 94, y: 81 },
|
||||
{ x: 22, y: 32 }, { x: 98, y: 96 },
|
||||
{ x: 12, y: 94 }, { x: 57, y: 58 },
|
||||
{ x: 31, y: 30 }, { x: 56, y: 7 },
|
||||
{ x: 60, y: 1 }, { x: 27, y: 47 },
|
||||
{ x: 74, y: 55 }, { x: 53, y: 70 },
|
||||
{ x: 48, y: 74 }, { x: 20, y: 68 },
|
||||
// { x: 47, y: 70 }, { x: 51, y: 27 },
|
||||
// { x: 93, y: 27 }, { x: 31, y: 88 },
|
||||
// { x: 25, y: 36 }, { x: 28, y: 31 },
|
||||
// { x: 44, y: 33 }, { x: 18, y: 56 },
|
||||
// { x: 80, y: 18 }, { x: 44, y: 65 },
|
||||
// { x: 0, y: 61 }, { x: 57, y: 55 },
|
||||
// { x: 39, y: 29 }, { x: 4, y: 39 },
|
||||
// { x: 83, y: 59 }, { x: 9, y: 38 },
|
||||
// { x: 28, y: 2 }, { x: 28, y: 73 },
|
||||
// { x: 72, y: 40 }
|
||||
];
|
||||
|
||||
// At least 3 points in each loop
|
||||
|
||||
// A*?
|
||||
// I'm nervous because this is a really poor match for A* on the face of it; A* excels at deep problems, but this is *really* shallow. Maybe that's fine? Because it's so shallow it shouldn't be that hard to finish any particular branch.
|
||||
// But we also might hit memory limitations.
|
||||
|
||||
// My intuition tells me brute force will be just out of reach. 33! solutions? / 3 for symmetry between the 3 loops. I think. 3 e 36.
|
||||
// At least several days
|
||||
|
||||
// let l = 0
|
||||
// for (let i = 0; i < 2.894439206E36; i ++) {
|
||||
// l += i;
|
||||
// if (i % 100000000 === 0) {
|
||||
// console.log(i / 2.894439206E36)
|
||||
// }
|
||||
// }
|
||||
// console.log(l);
|
||||
|
||||
// I'm going to give A* a shot
|
||||
// A node is a configuration of assigned loops and any unassigned points
|
||||
// A*'s nice because as soon as we find one solution that assigns all points, we have the minimum
|
||||
|
||||
// A* is best-first + heuristic, with the score being the current loop distance
|
||||
// The problem is we don't have a good heuristic
|
||||
|
||||
// Let's run best-first and see what happens
|
||||
|
||||
function distance (point1_id, point2_id) {
|
||||
const point1 = points[point1_id];
|
||||
const point2 = points[point2_id];
|
||||
return Math.sqrt((point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2);
|
||||
}
|
||||
|
||||
class State {
|
||||
constructor () {
|
||||
// super(); ???
|
||||
|
||||
// Three loops. Each one is a list of points
|
||||
// "point" refers to the index of the point in points, we're not copying them
|
||||
this.loops = [[], [], []];
|
||||
this.unassignedPoints = Array.range(points.length);
|
||||
// We can start off with the first point in the first loop
|
||||
this.assign(0, 0);
|
||||
}
|
||||
|
||||
assign (point_i, loop_i) {
|
||||
this.loops[loop_i].push(point_i);
|
||||
this.unassignedPoints.remove(point_i);
|
||||
this.updateScore();
|
||||
}
|
||||
|
||||
isComplete () {
|
||||
return this.unassignedPoints.length === 0;
|
||||
}
|
||||
|
||||
getIncompleteScore () {
|
||||
let score = 0;
|
||||
for (const loop of this.loops) {
|
||||
loop.windows(2).forEach(function (pair) {
|
||||
score += distance(...pair);
|
||||
});
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
getCompleteScore () {
|
||||
// The complete score is just the incomplete score + the distance to "close", from the last point to the first one
|
||||
let score = this.getIncompleteScore();
|
||||
for (const loop of loops) {
|
||||
score += distance(loop.last, loop.first);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
// Get the score
|
||||
getScore () {
|
||||
return this.isComplete() ? this.getCompleteScore() : this.getIncompleteScore();
|
||||
}
|
||||
|
||||
updateScore () {
|
||||
this.score = this.getScore();
|
||||
}
|
||||
|
||||
clone () {
|
||||
// This creates a new initial State, but that's fine
|
||||
const state = new State();
|
||||
state.unassignedPoints = this.unassignedPoints.copy();
|
||||
for (let i = 0; i < this.loops.length; i ++) {
|
||||
state.loops[i] = this.loops[i].copy();
|
||||
}
|
||||
state.updateScore();
|
||||
return state;
|
||||
}
|
||||
|
||||
// Return all possible next states
|
||||
getNextStates () {
|
||||
// if there aren't any, return []
|
||||
if (this.isComplete()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const nextStates = [];
|
||||
// Otherwise, we have the option of assigning any unassigned point to any of the three loops
|
||||
for (let i = 0; i < this.unassignedPoints.length; i++) {
|
||||
for (let j = 0; j < this.loops.length; j++) {
|
||||
const state = this.clone();
|
||||
state.assign(this.unassignedPoints[i], j);
|
||||
nextStates.push(state);
|
||||
}
|
||||
}
|
||||
return nextStates;
|
||||
}
|
||||
}
|
||||
|
||||
// Sorted by score of course
|
||||
// Best score at the end, so we can .pop() it
|
||||
// Best score is lowest of course
|
||||
const states = [new State()];
|
||||
|
||||
// console.log(states.first);
|
||||
// console.log(states.first.getNextStates());
|
||||
|
||||
// Insert 1 or more states preserving sort order
|
||||
function insertState (...states) {
|
||||
for (const state of states) {
|
||||
// i is the index that the state will end up at
|
||||
// If we're inserting at the end a lot, running this loop in reverse may be worth it
|
||||
let i = 0;
|
||||
while (i < states.length && states[i].score > state.score) {
|
||||
i ++;
|
||||
}
|
||||
states.splice(i, 0, state);
|
||||
}
|
||||
}
|
||||
|
||||
while (!states.last.isComplete()) {
|
||||
// process a state
|
||||
const state = states.pop();
|
||||
insertState(...state.getNextStates());
|
||||
}
|
||||
print(states);
|
|
@ -1,24 +0,0 @@
|
|||
require "nokogiri"
|
||||
|
||||
f = File.read("Linoleumherstellung.svg")
|
||||
|
||||
xml = Nokogiri::XML(f)
|
||||
|
||||
# binding.irb
|
||||
|
||||
# stack = [xml]
|
||||
# max_depth = 0
|
||||
|
||||
# until stack.empty?
|
||||
|
||||
# end
|
||||
|
||||
# Height is the number of edges, so a tree with two nodes has height 1
|
||||
# <foo> <bar> </bar> </foo>
|
||||
|
||||
def max_depth(tree)
|
||||
return 0 if tree.children.empty?
|
||||
return 1 + (tree.children.map { |c| max_depth c }).max
|
||||
end
|
||||
|
||||
p max_depth(xml)
|
Loading…
Reference in New Issue