init
This commit is contained in:
commit
0d84b22fa3
8 changed files with 1845 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
/ignore
|
||||||
75
Cargo.lock
generated
Normal file
75
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.155"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oh-hi-solver"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "oh-hi-solver"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rand = "0.8"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
113
flake.lock
generated
Normal file
113
flake.lock
generated
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1705309234,
|
||||||
|
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681202837,
|
||||||
|
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1717974879,
|
||||||
|
"narHash": "sha256-GTO3C88+5DX171F/gVS3Qga/hOs/eRMxPFpiHq2t+D8=",
|
||||||
|
"path": "/nix/store/rljkm6h18fjvavm6l17jiil8glphc44f-source",
|
||||||
|
"rev": "c7b821ba2e1e635ba5a76d299af62821cbcb09f3",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"rust-overlay": "rust-overlay"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1705889935,
|
||||||
|
"narHash": "sha256-77KPBK5e0ACNzIgJDMuptTtEqKvHBxTO3ksqXHHVO+4=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "e36f66bb10b09f5189dc3b1706948eaeb9a1c555",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
28
flake.nix
Normal file
28
flake.nix
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
description = "nix dev environment";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
#nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||||
|
rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils, rust-overlay, ... }:
|
||||||
|
flake-utils.lib.eachDefaultSystem(system:
|
||||||
|
let
|
||||||
|
overlays = [ (import rust-overlay) ];
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system overlays;
|
||||||
|
};
|
||||||
|
toolchain = pkgs.rust-bin.fromRustupToolchain { channel = "nightly-2024-01-22"; };
|
||||||
|
in {
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
pkg-config
|
||||||
|
openssl
|
||||||
|
toolchain
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
697
src/gen.rs
Normal file
697
src/gen.rs
Normal file
|
|
@ -0,0 +1,697 @@
|
||||||
|
#![feature(iter_intersperse)]
|
||||||
|
|
||||||
|
const GRID: &str = r#"
|
||||||
|
..y..bb.....
|
||||||
|
.....b.b.bb.
|
||||||
|
bb..........
|
||||||
|
b.yb......y.
|
||||||
|
.....b...b..
|
||||||
|
.yb...b.....
|
||||||
|
....y..yy...
|
||||||
|
...b....y..y
|
||||||
|
.....yy....y
|
||||||
|
..yy.....y..
|
||||||
|
.b..........
|
||||||
|
b..b.y.b....
|
||||||
|
"#;
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Grid {
|
||||||
|
pub cells: Vec<Colour>,
|
||||||
|
dimension: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Colour {
|
||||||
|
None,
|
||||||
|
Yellow,
|
||||||
|
Blue
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Colour {
|
||||||
|
pub fn map_none<F>(self, mut cb: F) -> Colour
|
||||||
|
where F: FnMut() -> Colour {
|
||||||
|
if self == Colour::None {
|
||||||
|
cb()
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Grid {
|
||||||
|
pub fn new(dimension: usize) -> Self {
|
||||||
|
let cells = vec![Colour::None; dimension * dimension];
|
||||||
|
|
||||||
|
Self {
|
||||||
|
cells,
|
||||||
|
dimension
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn up(&self, cell: usize) -> Option<usize> {
|
||||||
|
if cell < self.dimension {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(cell - self.dimension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn down(&self, cell: usize) -> Option<usize> {
|
||||||
|
if cell >= self.cells.capacity() - self.dimension {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(cell + self.dimension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn left(&self, cell: usize) -> Option<usize> {
|
||||||
|
if cell % self.dimension == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(cell - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn right(&self, cell: usize) -> Option<usize> {
|
||||||
|
if (cell + 1) % self.dimension == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(cell + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_pos(&self, x: usize, y: usize) -> Option<usize> {
|
||||||
|
if x > self.dimension - 1 || y > self.dimension - 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(self.dimension * y + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate_alt(&mut self, input: &str) -> &mut Self {
|
||||||
|
let mut i = 0;
|
||||||
|
for ch in input.chars().filter(|c| !c.is_whitespace()) {
|
||||||
|
if i >= self.cells.len() {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
let colour = match ch {
|
||||||
|
'0' | 'y' => Colour::Yellow,
|
||||||
|
'1' | 'b' => Colour::Blue,
|
||||||
|
_ => Colour::None,
|
||||||
|
};
|
||||||
|
self.cells[i] = colour;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate(&mut self, cells: &[(usize, usize, usize)]) -> &mut Self {
|
||||||
|
for (x, y, colour) in cells.into_iter() {
|
||||||
|
let pos = self.from_pos(*x, *y);
|
||||||
|
if pos.is_none() {
|
||||||
|
panic!("OOB");
|
||||||
|
}
|
||||||
|
let pos = pos.unwrap();
|
||||||
|
let colour = match colour {
|
||||||
|
0 => Colour::Yellow,
|
||||||
|
1 => Colour::Blue,
|
||||||
|
_ => panic!("Unknown colour")
|
||||||
|
};
|
||||||
|
self.cells[pos] = colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_rows(&self) -> Vec<&[Colour]> {
|
||||||
|
let mut vec = Vec::with_capacity(self.dimension);
|
||||||
|
for row in 0..self.dimension {
|
||||||
|
let firstcell = self.dimension * row;
|
||||||
|
let lastbound = firstcell + self.dimension;
|
||||||
|
vec.push(&self.cells[firstcell..lastbound]);
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_cols(&self) -> Vec<Vec<Colour>> {
|
||||||
|
let mut vec = Vec::with_capacity(self.dimension);
|
||||||
|
for col in 0..=self.dimension {
|
||||||
|
let v = self.cells.iter().skip(col).step_by(self.dimension).cloned().collect::<Vec<_>>();
|
||||||
|
vec.push(v);
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(&self) {
|
||||||
|
let mut i = 0;
|
||||||
|
for cell in &self.cells {
|
||||||
|
i += 1;
|
||||||
|
let res = match cell {
|
||||||
|
Colour::Yellow => "y",
|
||||||
|
Colour::Blue => "b",
|
||||||
|
Colour::None => "?",
|
||||||
|
};
|
||||||
|
print!("{}", res);
|
||||||
|
if i % self.dimension == 0 {
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct Grid<const LENGTH: usize> {
|
||||||
|
// cells: [Option<bool>; LENGTH],
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut grid = Grid::new(12);
|
||||||
|
|
||||||
|
grid.populate_alt(GRID);
|
||||||
|
|
||||||
|
grid.print();
|
||||||
|
println!();
|
||||||
|
|
||||||
|
let mut oi = 0;
|
||||||
|
let mut ii = 0;
|
||||||
|
let mut ui = 0;
|
||||||
|
let mut uit = 0;
|
||||||
|
let mut cht = 0;
|
||||||
|
let mut chl = vec![];
|
||||||
|
let mut trace = [0u8; 10];
|
||||||
|
let mut secondary_trace = vec![];
|
||||||
|
|
||||||
|
for _ in 0..=grid.cells.len() {
|
||||||
|
oi += 1;
|
||||||
|
let mut changed = false;
|
||||||
|
let mut chi = 0;
|
||||||
|
for cell in 0..(grid.cells.len()) {
|
||||||
|
if grid.cells[cell] != Colour::None {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ii += 1;
|
||||||
|
let colour = test_eqrow(&grid, cell, &mut trace[0], &mut secondary_trace)
|
||||||
|
.map_none(|| test_eqcol(&grid, cell, &mut trace[1], &mut secondary_trace))
|
||||||
|
.map_none(|| test_neighbour_hori(&grid, cell, &mut trace[2], &mut secondary_trace))
|
||||||
|
.map_none(|| test_neighbour_vert(&grid, cell, &mut trace[3], &mut secondary_trace))
|
||||||
|
.map_none(|| test_double_horileft(&grid, cell, &mut trace[4], &mut secondary_trace))
|
||||||
|
.map_none(|| test_double_horiright(&grid, cell, &mut trace[5], &mut secondary_trace))
|
||||||
|
.map_none(|| test_double_vertup(&grid, cell, &mut trace[6], &mut secondary_trace))
|
||||||
|
.map_none(|| test_double_vertdown(&grid, cell, &mut trace[7], &mut secondary_trace));
|
||||||
|
|
||||||
|
if colour != Colour::None {
|
||||||
|
cht += 1;
|
||||||
|
chi += 1;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
grid.cells[cell] = colour;
|
||||||
|
}
|
||||||
|
chl.push(chi);
|
||||||
|
if !changed {
|
||||||
|
uit += 1;
|
||||||
|
for cell in 0..(grid.cells.len()) {
|
||||||
|
if grid.cells[cell] != Colour::None {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let colour = test_matching_row(&grid, cell, &mut trace[8], &mut secondary_trace)
|
||||||
|
.map_none(|| test_matching_col(&grid, cell, &mut trace[9], &mut secondary_trace));
|
||||||
|
|
||||||
|
if colour != Colour::None {
|
||||||
|
ui += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
grid.cells[cell] = colour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !grid.cells.contains(&Colour::None) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
|
||||||
|
let solved = !grid.cells.contains(&Colour::None);
|
||||||
|
|
||||||
|
grid.print();
|
||||||
|
println!();
|
||||||
|
println!("{}", if solved { "solved" } else { "unsolved" });
|
||||||
|
println!("iter: {}/{}", oi, grid.cells.len() + 1);
|
||||||
|
println!("checked: {}+{}/{}/{}/{}", cht, ui, ii, oi * grid.cells.len(), grid.cells.len() * (grid.cells.len() + 1));
|
||||||
|
println!("matching check: {}/{}", ui, uit);
|
||||||
|
println!("chl: {:?}", chl);
|
||||||
|
println!("- eqrow: {}", trace[0]);
|
||||||
|
println!("- eqcol: {}", trace[1]);
|
||||||
|
println!("- neighbour_hori: {}", trace[2]);
|
||||||
|
println!("- neighbour_vert: {}", trace[3]);
|
||||||
|
println!("- double_horileft: {}", trace[4]);
|
||||||
|
println!("- double_horiright: {}", trace[5]);
|
||||||
|
println!("- double_vertup: {}", trace[6]);
|
||||||
|
println!("- double_vertdown: {}", trace[7]);
|
||||||
|
println!("- matching_row: {}", trace[8]);
|
||||||
|
println!("- matching_col: {}", trace[9]);
|
||||||
|
let mut bo = false;
|
||||||
|
println!("seq: {}", secondary_trace
|
||||||
|
.into_iter()
|
||||||
|
.map(|u| u.to_string())
|
||||||
|
.intersperse_with(|| {
|
||||||
|
bo = !bo;
|
||||||
|
if bo {
|
||||||
|
".".to_string()
|
||||||
|
} else {
|
||||||
|
"_".to_string()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<String>());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_eqrow(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let mut yellow = 0;
|
||||||
|
let mut blue = 0;
|
||||||
|
|
||||||
|
let mut nextleft = cell;
|
||||||
|
loop {
|
||||||
|
let nextref = grid.left(nextleft);
|
||||||
|
if let Some(nextref) = nextref {
|
||||||
|
let colour = grid.cells[nextref];
|
||||||
|
match colour {
|
||||||
|
Colour::Yellow => yellow += 1,
|
||||||
|
Colour::Blue => blue += 1,
|
||||||
|
Colour::None => (),
|
||||||
|
};
|
||||||
|
if yellow == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(0);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Blue;
|
||||||
|
}
|
||||||
|
if blue == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(0);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Yellow;
|
||||||
|
}
|
||||||
|
nextleft = nextref;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut nextright = cell;
|
||||||
|
loop {
|
||||||
|
let nextref = grid.right(nextright);
|
||||||
|
if let Some(nextref) = nextref {
|
||||||
|
let colour = grid.cells[nextref];
|
||||||
|
match colour {
|
||||||
|
Colour::Yellow => yellow += 1,
|
||||||
|
Colour::Blue => blue += 1,
|
||||||
|
Colour::None => (),
|
||||||
|
};
|
||||||
|
if yellow == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(0);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Blue;
|
||||||
|
}
|
||||||
|
if blue == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(0);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Yellow;
|
||||||
|
}
|
||||||
|
nextright = nextref;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_eqcol(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let mut yellow = 0;
|
||||||
|
let mut blue = 0;
|
||||||
|
|
||||||
|
let mut nextup = cell;
|
||||||
|
loop {
|
||||||
|
let nextref = grid.up(nextup);
|
||||||
|
if let Some(nextref) = nextref {
|
||||||
|
let colour = grid.cells[nextref];
|
||||||
|
match colour {
|
||||||
|
Colour::Yellow => yellow += 1,
|
||||||
|
Colour::Blue => blue += 1,
|
||||||
|
Colour::None => (),
|
||||||
|
};
|
||||||
|
if yellow == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(1);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Blue;
|
||||||
|
}
|
||||||
|
if blue == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(1);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Yellow;
|
||||||
|
}
|
||||||
|
nextup = nextref;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut nextdown = cell;
|
||||||
|
loop {
|
||||||
|
let nextref = grid.down(nextdown);
|
||||||
|
if let Some(nextref) = nextref {
|
||||||
|
let colour = grid.cells[nextref];
|
||||||
|
match colour {
|
||||||
|
Colour::Yellow => yellow += 1,
|
||||||
|
Colour::Blue => blue += 1,
|
||||||
|
Colour::None => (),
|
||||||
|
};
|
||||||
|
if yellow == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(1);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Blue;
|
||||||
|
}
|
||||||
|
if blue == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(1);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Yellow;
|
||||||
|
}
|
||||||
|
nextdown = nextref;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_neighbour_vert(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let above = grid.up(cell);
|
||||||
|
if above.is_none() {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
let above = grid.cells[above.unwrap()];
|
||||||
|
|
||||||
|
let below = grid.down(cell);
|
||||||
|
if below.is_none() {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
let below = grid.cells[below.unwrap()];
|
||||||
|
|
||||||
|
if above == below {
|
||||||
|
if above != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(2);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match above {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_neighbour_hori(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let left = grid.left(cell);
|
||||||
|
if left.is_none() {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
let left = grid.cells[left.unwrap()];
|
||||||
|
|
||||||
|
let right = grid.right(cell);
|
||||||
|
if right.is_none() {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
let right = grid.cells[right.unwrap()];
|
||||||
|
|
||||||
|
if left == right {
|
||||||
|
if left != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(3);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match left {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_double_horileft(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
//let target = grid.from_pos(9, 1).unwrap();
|
||||||
|
|
||||||
|
let leftref = grid.left(cell);
|
||||||
|
//if cell == target { println!("a {:?}", leftref) };
|
||||||
|
if let Some(leftref) = leftref {
|
||||||
|
let left = grid.cells[leftref];
|
||||||
|
let lefter = grid.left(leftref).map(|lefterref| grid.cells[lefterref]).unwrap_or(Colour::None);
|
||||||
|
|
||||||
|
//if cell == target { println!("{:?}, {:?}", left, lefter) };
|
||||||
|
|
||||||
|
if left == lefter {
|
||||||
|
if left != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(4);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match left {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_double_horiright(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let rightref = grid.right(cell);
|
||||||
|
//if cell == target { println!("b {:?}", leftref) };
|
||||||
|
if let Some(rightref) = rightref {
|
||||||
|
let right = grid.cells[rightref];
|
||||||
|
let righter = grid.right(rightref).map(|righterref| grid.cells[righterref]).unwrap_or(Colour::None);
|
||||||
|
//if cell == target { println!("{:?}, {:?}", right, righter) };
|
||||||
|
if right == righter {
|
||||||
|
if right != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(5);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match right {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_double_vertup(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let upref = grid.up(cell);
|
||||||
|
if let Some(upref) = upref {
|
||||||
|
let up = grid.cells[upref];
|
||||||
|
let upper = grid.up(upref).map(|upperref| grid.cells[upperref]).unwrap_or(Colour::None);
|
||||||
|
if up == upper {
|
||||||
|
if up != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(6);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match up {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_double_vertdown(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let downref = grid.down(cell);
|
||||||
|
if let Some(downref) = downref {
|
||||||
|
let down = grid.cells[downref];
|
||||||
|
let downer = grid.down(downref).map(|downerref| grid.cells[downerref]).unwrap_or(Colour::None);
|
||||||
|
if down == downer {
|
||||||
|
if down != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(7);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match down {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_matching_row(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let rows = grid.as_rows();
|
||||||
|
let cellrow = rows[cell / grid.dimension];
|
||||||
|
let ncount = cellrow.iter().filter(|e| **e == Colour::None).count();
|
||||||
|
if ncount != 2 {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
'outer: for row in rows {
|
||||||
|
if std::ptr::eq(row, cellrow) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..grid.dimension {
|
||||||
|
let current = cellrow[i];
|
||||||
|
let against = row[i];
|
||||||
|
if current != Colour::None && current != against {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_none = cellrow.iter().position(|e| *e == Colour::None).unwrap();
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(8);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return match row[first_none] {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => unreachable!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_matching_col(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let cols = grid.as_cols();
|
||||||
|
let cellcol = &cols[cell % grid.dimension];
|
||||||
|
let ncount = cellcol.iter().filter(|e| **e == Colour::None).count();
|
||||||
|
if ncount != 2 {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
'outer: for col in &cols {
|
||||||
|
if col == cellcol {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..grid.dimension {
|
||||||
|
let current = cellcol[i];
|
||||||
|
let against = col[i];
|
||||||
|
if against == Colour::None {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
if current != Colour::None && current != against {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_none = cellcol.iter().position(|e| *e == Colour::None).unwrap();
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(9);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return match col[first_none] {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => unreachable!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
pub struct ListNode {
|
||||||
|
pub val: i32,
|
||||||
|
pub next: Option<Box<ListNode>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListNode {
|
||||||
|
#[inline]
|
||||||
|
fn new(val: i32) -> Self {
|
||||||
|
ListNode {
|
||||||
|
next: None,
|
||||||
|
val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
|
||||||
|
let mut res = vec![];
|
||||||
|
|
||||||
|
let mut p1 = l1;
|
||||||
|
let mut p2 = l2;
|
||||||
|
let mut rollover = false;
|
||||||
|
loop {
|
||||||
|
if p1.is_none() && p2.is_none() {
|
||||||
|
if rollover {
|
||||||
|
res.push(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let v1;
|
||||||
|
if let Some(p1u) = p1 {
|
||||||
|
v1 = p1u.val;
|
||||||
|
p1 = p1u.next;
|
||||||
|
} else {
|
||||||
|
v1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let v2;
|
||||||
|
if let Some(p2u) = p2 {
|
||||||
|
v2 = p2u.val;
|
||||||
|
p2 = p2u.next;
|
||||||
|
} else {
|
||||||
|
v2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut nw = v1 + v2;
|
||||||
|
if rollover {
|
||||||
|
nw += 1;
|
||||||
|
rollover = false;
|
||||||
|
}
|
||||||
|
if nw > 9 {
|
||||||
|
nw -= 10;
|
||||||
|
rollover = true;
|
||||||
|
}
|
||||||
|
res.push(nw);
|
||||||
|
|
||||||
|
// if res.val == -1 {
|
||||||
|
// res = Box::new(npr);
|
||||||
|
// last = ⊀
|
||||||
|
// } else {
|
||||||
|
// # let mut o = Box::new(ListNode::new(nextp));
|
||||||
|
// # last.next = Some(o);
|
||||||
|
// # last = &mut o;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
let mut prev: Option<Box<ListNode>> = None;
|
||||||
|
for i in res.into_iter().rev() {
|
||||||
|
let mut np = ListNode::new(i);
|
||||||
|
np.next = prev;
|
||||||
|
prev = Some(Box::new(np));
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
917
src/main.rs
Normal file
917
src/main.rs
Normal file
|
|
@ -0,0 +1,917 @@
|
||||||
|
#![feature(iter_intersperse)]
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
use std::ptr::null;
|
||||||
|
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
// Array.from(document.getElementById("grid").children[0].children).map(i => Array.from(i.children).map(l => l.children[0].classList[1] === "tile-" ? "." : (l.children[0].classList[1] === "tile-1" ? "b" : "y"))).flat().join("")
|
||||||
|
|
||||||
|
const GRID: &str = r#"
|
||||||
|
..y..bb.....
|
||||||
|
.....b.b.bb.
|
||||||
|
bb..........
|
||||||
|
b.yb......y.
|
||||||
|
.....b...b..
|
||||||
|
.yb...b.....
|
||||||
|
....y..yy...
|
||||||
|
...b....y..y
|
||||||
|
.....yy....y
|
||||||
|
..yy.....y..
|
||||||
|
.b..........
|
||||||
|
b..b.y.b....
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const SOLVED: &str = r#"
|
||||||
|
ybybybbybyyb
|
||||||
|
yybybbybybby
|
||||||
|
bbyybybybyby
|
||||||
|
byybybyybbyb
|
||||||
|
ybbybbybybyy
|
||||||
|
yybybybybybb
|
||||||
|
bbybyybyybyb
|
||||||
|
yybbybybybby
|
||||||
|
bybybyybbyby
|
||||||
|
bbyybybybyyb
|
||||||
|
ybybybybybyb
|
||||||
|
bybbyybbyyby
|
||||||
|
"#;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Grid {
|
||||||
|
pub cells: Vec<Colour>,
|
||||||
|
dimension: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Colour {
|
||||||
|
None,
|
||||||
|
Yellow,
|
||||||
|
Blue
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Colour {
|
||||||
|
pub fn map_none<F>(self, mut cb: F) -> Colour
|
||||||
|
where F: FnMut() -> Colour {
|
||||||
|
if self == Colour::None {
|
||||||
|
cb()
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_i8(&self) -> i8 {
|
||||||
|
match self {
|
||||||
|
Colour::None => 0,
|
||||||
|
Colour::Yellow => 1,
|
||||||
|
Colour::Blue => 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Grid {
|
||||||
|
pub fn new(dimension: usize) -> Self {
|
||||||
|
let cells = vec![Colour::None; dimension * dimension];
|
||||||
|
|
||||||
|
Self {
|
||||||
|
cells,
|
||||||
|
dimension
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn up(&self, cell: usize) -> Option<usize> {
|
||||||
|
if cell < self.dimension {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(cell - self.dimension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn down(&self, cell: usize) -> Option<usize> {
|
||||||
|
if cell >= self.cells.capacity() - self.dimension {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(cell + self.dimension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn left(&self, cell: usize) -> Option<usize> {
|
||||||
|
if cell % self.dimension == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(cell - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn right(&self, cell: usize) -> Option<usize> {
|
||||||
|
if (cell + 1) % self.dimension == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(cell + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_pos(&self, x: usize, y: usize) -> Option<usize> {
|
||||||
|
if x > self.dimension - 1 || y > self.dimension - 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(self.dimension * y + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate_alt(&mut self, input: &str) -> &mut Self {
|
||||||
|
let mut i = 0;
|
||||||
|
for ch in input.chars().filter(|c| !c.is_whitespace()) {
|
||||||
|
if i >= self.cells.len() {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
let colour = match ch {
|
||||||
|
'0' | 'y' => Colour::Yellow,
|
||||||
|
'1' | 'b' => Colour::Blue,
|
||||||
|
_ => Colour::None,
|
||||||
|
};
|
||||||
|
self.cells[i] = colour;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate(&mut self, cells: &[(usize, usize, usize)]) -> &mut Self {
|
||||||
|
for (x, y, colour) in cells.into_iter() {
|
||||||
|
let pos = self.from_pos(*x, *y);
|
||||||
|
if pos.is_none() {
|
||||||
|
panic!("OOB");
|
||||||
|
}
|
||||||
|
let pos = pos.unwrap();
|
||||||
|
let colour = match colour {
|
||||||
|
0 => Colour::Yellow,
|
||||||
|
1 => Colour::Blue,
|
||||||
|
_ => panic!("Unknown colour")
|
||||||
|
};
|
||||||
|
self.cells[pos] = colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_rows(&self) -> Vec<&[Colour]> {
|
||||||
|
let mut vec = Vec::with_capacity(self.dimension);
|
||||||
|
for row in 0..self.dimension {
|
||||||
|
let firstcell = self.dimension * row;
|
||||||
|
let lastbound = firstcell + self.dimension;
|
||||||
|
vec.push(&self.cells[firstcell..lastbound]);
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
/**pub fn as_cols(&self) -> Vec<Vec<&Colour>> {
|
||||||
|
if let Some(c) = self.cols {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut vec = vec![vec![]; self.dimension];
|
||||||
|
let mut i = 0;
|
||||||
|
for cell in &self.cells {
|
||||||
|
let oi = i / self.dimension;
|
||||||
|
let ii = i % self.dimension;
|
||||||
|
vec[oi].push(cell);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __as_cols(&self) -> Vec<Vec<Colour>> {
|
||||||
|
let mut vec = vec![vec![Colour::None; self.dimension]; self.dimension];
|
||||||
|
let mut i = 0;
|
||||||
|
for cell in &self.cells {
|
||||||
|
let oi = i / self.dimension;
|
||||||
|
let ii = i % self.dimension;
|
||||||
|
vec[oi][ii] = *cell;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
}*/
|
||||||
|
|
||||||
|
pub fn as_cols(&self) -> Vec<Vec<Colour>> {
|
||||||
|
let mut vec = Vec::with_capacity(self.dimension);
|
||||||
|
for col in 0..self.dimension {
|
||||||
|
let v = self.cells.iter().skip(col).step_by(self.dimension).cloned().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
vec.push(v);
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(&self) {
|
||||||
|
let mut i = 0;
|
||||||
|
for cell in &self.cells {
|
||||||
|
i += 1;
|
||||||
|
let res = match cell {
|
||||||
|
Colour::Yellow => "y",
|
||||||
|
Colour::Blue => "b",
|
||||||
|
Colour::None => "?",
|
||||||
|
};
|
||||||
|
print!("{}", res);
|
||||||
|
if i % self.dimension == 0 {
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct Grid<const LENGTH: usize> {
|
||||||
|
// cells: [Option<bool>; LENGTH],
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
{
|
||||||
|
let args = std::env::args().collect::<Vec<String>>();
|
||||||
|
let raw = args.into_iter().skip(1).next().unwrap_or(GRID.to_string());
|
||||||
|
println!("{}", raw);
|
||||||
|
sd(&raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _main()
|
||||||
|
{
|
||||||
|
let mut g: Grid = Grid::new(12);
|
||||||
|
|
||||||
|
let mut prev = 150;
|
||||||
|
|
||||||
|
for _ in 0..1 {
|
||||||
|
let (counter, last_len, grid) = gen();
|
||||||
|
|
||||||
|
if last_len < prev {
|
||||||
|
prev = last_len;
|
||||||
|
g = grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("it {}, ln {}", counter, last_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
println!();
|
||||||
|
println!();
|
||||||
|
|
||||||
|
println!("iterations: {}", counter);
|
||||||
|
println!("filled: {}/{}", last_len, 12 * 12);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
g.print();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen() -> (usize, i32, Grid) {
|
||||||
|
let mut grid = Grid::new(12);
|
||||||
|
grid.populate_alt(SOLVED);
|
||||||
|
|
||||||
|
let mut chq: Vec<usize> = vec![0; 12*12];
|
||||||
|
let mut counter = 0;
|
||||||
|
chq.fill_with(|| { let a = counter; counter += 1; a });
|
||||||
|
counter = 0;
|
||||||
|
let mut last_len = 12 * 12;
|
||||||
|
loop {
|
||||||
|
counter += 1;
|
||||||
|
if chq.len() == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//let i = rand::thread_rng().gen_range(0..chq.len());
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
let mut clone = grid.clone();
|
||||||
|
clone.cells[chq[i]] = Colour::None;
|
||||||
|
chq.swap_remove(i);
|
||||||
|
let (solved, _) = solve(&mut clone.clone());
|
||||||
|
|
||||||
|
if solved {
|
||||||
|
last_len -= 1;
|
||||||
|
grid = clone;
|
||||||
|
chq = vec![];
|
||||||
|
for (i, col) in grid.cells.iter().enumerate() {
|
||||||
|
if *col != Colour::None {
|
||||||
|
chq.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// print!(".");
|
||||||
|
// let _ = std::io::stdout().flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (counter, last_len, grid);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sd(raw: &str) {
|
||||||
|
let mut grid = Grid::new(12);
|
||||||
|
|
||||||
|
grid.populate_alt(raw);
|
||||||
|
|
||||||
|
let ogrid = grid.clone();
|
||||||
|
|
||||||
|
grid.print();
|
||||||
|
println!();
|
||||||
|
|
||||||
|
let (solved, (oi, ii, ui, uit, cht, chl, trace, secondary_trace)) = solve(&mut grid);
|
||||||
|
|
||||||
|
grid.print();
|
||||||
|
println!();
|
||||||
|
println!("{}", if solved { "solved" } else { "unsolved" });
|
||||||
|
println!("iter: {}/{}", oi, grid.cells.len() + 1);
|
||||||
|
println!("checked: {}+{}/{}/{}/{}", cht, ui, ii, oi * grid.cells.len() as i32, grid.cells.len() * (grid.cells.len() + 1));
|
||||||
|
println!("matching check: {}/{}", ui, uit);
|
||||||
|
println!("chl: {:?}", chl);
|
||||||
|
println!("- eqrow: {}", trace[0]);
|
||||||
|
println!("- eqcol: {}", trace[1]);
|
||||||
|
println!("- neighbour_hori: {}", trace[2]);
|
||||||
|
println!("- neighbour_vert: {}", trace[3]);
|
||||||
|
println!("- double_horileft: {}", trace[4]);
|
||||||
|
println!("- double_horiright: {}", trace[5]);
|
||||||
|
println!("- double_vertup: {}", trace[6]);
|
||||||
|
println!("- double_vertdown: {}", trace[7]);
|
||||||
|
println!("- matching_row: {}", trace[8]);
|
||||||
|
println!("- matching_col: {}", trace[9]);
|
||||||
|
let mut bo = false;
|
||||||
|
println!("seq: {}", secondary_trace
|
||||||
|
.into_iter()
|
||||||
|
.map(|u| u.to_string())
|
||||||
|
.intersperse_with(|| {
|
||||||
|
bo = !bo;
|
||||||
|
if bo {
|
||||||
|
".".to_string()
|
||||||
|
} else {
|
||||||
|
"_".to_string()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<String>());
|
||||||
|
|
||||||
|
println!("{}", diff(&ogrid, &grid));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn diff(grid1: &Grid, grid2: &Grid) -> String {
|
||||||
|
let mut str = String::with_capacity(grid1.dimension * grid1.dimension);
|
||||||
|
for i in 0..(grid1.dimension * grid1.dimension) {
|
||||||
|
let c1 = grid1.cells[i].as_i8();
|
||||||
|
let c2 = grid2.cells[i].as_i8();
|
||||||
|
let mut diff = c2 - c1;
|
||||||
|
if diff < 0 {
|
||||||
|
diff += 2;
|
||||||
|
}
|
||||||
|
str += &diff.to_string();
|
||||||
|
}
|
||||||
|
str
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve(grid: &mut Grid) -> (bool, (i32, i32, i32, i32, i32, Vec<i32>, [u8; 10], Vec<usize>)) {
|
||||||
|
let mut oi = 0;
|
||||||
|
let mut ii = 0;
|
||||||
|
let mut ui = 0;
|
||||||
|
let mut uit = 0;
|
||||||
|
let mut cht = 0;
|
||||||
|
let mut chl = vec![];
|
||||||
|
let mut trace = [0u8; 10];
|
||||||
|
let mut secondary_trace = vec![];
|
||||||
|
|
||||||
|
for _ in 0..=grid.cells.len() {
|
||||||
|
oi += 1;
|
||||||
|
let mut changed = false;
|
||||||
|
let mut chi = 0;
|
||||||
|
for cell in 0..(grid.cells.len()) {
|
||||||
|
if grid.cells[cell] != Colour::None {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ii += 1;
|
||||||
|
let colour = test_eqrow(&grid, cell, &mut trace[0], &mut secondary_trace)
|
||||||
|
.map_none(|| test_eqcol(&grid, cell, &mut trace[1], &mut secondary_trace))
|
||||||
|
.map_none(|| test_neighbour_hori(&grid, cell, &mut trace[2], &mut secondary_trace))
|
||||||
|
.map_none(|| test_neighbour_vert(&grid, cell, &mut trace[3], &mut secondary_trace))
|
||||||
|
.map_none(|| test_double_horileft(&grid, cell, &mut trace[4], &mut secondary_trace))
|
||||||
|
.map_none(|| test_double_horiright(&grid, cell, &mut trace[5], &mut secondary_trace))
|
||||||
|
.map_none(|| test_double_vertup(&grid, cell, &mut trace[6], &mut secondary_trace))
|
||||||
|
.map_none(|| test_double_vertdown(&grid, cell, &mut trace[7], &mut secondary_trace));
|
||||||
|
|
||||||
|
if colour != Colour::None {
|
||||||
|
cht += 1;
|
||||||
|
chi += 1;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
grid.cells[cell] = colour;
|
||||||
|
}
|
||||||
|
chl.push(chi);
|
||||||
|
if !changed {
|
||||||
|
uit += 1;
|
||||||
|
for cell in 0..(grid.cells.len()) {
|
||||||
|
if grid.cells[cell] != Colour::None {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let colour = test_matching_row(&grid, cell, &mut trace[8], &mut secondary_trace)
|
||||||
|
.map_none(|| test_matching_col(&grid, cell, &mut trace[9], &mut secondary_trace));
|
||||||
|
|
||||||
|
if colour != Colour::None {
|
||||||
|
ui += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
grid.cells[cell] = colour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !grid.cells.contains(&Colour::None) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let solved = !grid.cells.contains(&Colour::None);
|
||||||
|
return (solved, (oi, ii, ui, uit, cht, chl, trace, secondary_trace));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_eqrow(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let mut yellow = 0;
|
||||||
|
let mut blue = 0;
|
||||||
|
|
||||||
|
let mut nextleft = cell;
|
||||||
|
loop {
|
||||||
|
let nextref = grid.left(nextleft);
|
||||||
|
if let Some(nextref) = nextref {
|
||||||
|
let colour = grid.cells[nextref];
|
||||||
|
match colour {
|
||||||
|
Colour::Yellow => yellow += 1,
|
||||||
|
Colour::Blue => blue += 1,
|
||||||
|
Colour::None => (),
|
||||||
|
};
|
||||||
|
if yellow == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(0);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Blue;
|
||||||
|
}
|
||||||
|
if blue == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(0);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Yellow;
|
||||||
|
}
|
||||||
|
nextleft = nextref;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut nextright = cell;
|
||||||
|
loop {
|
||||||
|
let nextref = grid.right(nextright);
|
||||||
|
if let Some(nextref) = nextref {
|
||||||
|
let colour = grid.cells[nextref];
|
||||||
|
match colour {
|
||||||
|
Colour::Yellow => yellow += 1,
|
||||||
|
Colour::Blue => blue += 1,
|
||||||
|
Colour::None => (),
|
||||||
|
};
|
||||||
|
if yellow == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(0);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Blue;
|
||||||
|
}
|
||||||
|
if blue == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(0);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Yellow;
|
||||||
|
}
|
||||||
|
nextright = nextref;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_eqcol(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let mut yellow = 0;
|
||||||
|
let mut blue = 0;
|
||||||
|
|
||||||
|
let mut nextup = cell;
|
||||||
|
loop {
|
||||||
|
let nextref = grid.up(nextup);
|
||||||
|
if let Some(nextref) = nextref {
|
||||||
|
let colour = grid.cells[nextref];
|
||||||
|
match colour {
|
||||||
|
Colour::Yellow => yellow += 1,
|
||||||
|
Colour::Blue => blue += 1,
|
||||||
|
Colour::None => (),
|
||||||
|
};
|
||||||
|
if yellow == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(1);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Blue;
|
||||||
|
}
|
||||||
|
if blue == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(1);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Yellow;
|
||||||
|
}
|
||||||
|
nextup = nextref;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut nextdown = cell;
|
||||||
|
loop {
|
||||||
|
let nextref = grid.down(nextdown);
|
||||||
|
if let Some(nextref) = nextref {
|
||||||
|
let colour = grid.cells[nextref];
|
||||||
|
match colour {
|
||||||
|
Colour::Yellow => yellow += 1,
|
||||||
|
Colour::Blue => blue += 1,
|
||||||
|
Colour::None => (),
|
||||||
|
};
|
||||||
|
if yellow == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(1);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Blue;
|
||||||
|
}
|
||||||
|
if blue == grid.dimension / 2 {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(1);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return Colour::Yellow;
|
||||||
|
}
|
||||||
|
nextdown = nextref;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_neighbour_vert(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let above = grid.up(cell);
|
||||||
|
if above.is_none() {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
let above = grid.cells[above.unwrap()];
|
||||||
|
|
||||||
|
let below = grid.down(cell);
|
||||||
|
if below.is_none() {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
let below = grid.cells[below.unwrap()];
|
||||||
|
|
||||||
|
if above == below {
|
||||||
|
if above != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(2);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match above {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_neighbour_hori(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let left = grid.left(cell);
|
||||||
|
if left.is_none() {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
let left = grid.cells[left.unwrap()];
|
||||||
|
|
||||||
|
let right = grid.right(cell);
|
||||||
|
if right.is_none() {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
let right = grid.cells[right.unwrap()];
|
||||||
|
|
||||||
|
if left == right {
|
||||||
|
if left != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(3);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match left {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_double_horileft(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
//let target = grid.from_pos(9, 1).unwrap();
|
||||||
|
|
||||||
|
let leftref = grid.left(cell);
|
||||||
|
//if cell == target { println!("a {:?}", leftref) };
|
||||||
|
if let Some(leftref) = leftref {
|
||||||
|
let left = grid.cells[leftref];
|
||||||
|
let lefter = grid.left(leftref).map(|lefterref| grid.cells[lefterref]).unwrap_or(Colour::None);
|
||||||
|
|
||||||
|
//if cell == target { println!("{:?}, {:?}", left, lefter) };
|
||||||
|
|
||||||
|
if left == lefter {
|
||||||
|
if left != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(4);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match left {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_double_horiright(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let rightref = grid.right(cell);
|
||||||
|
//if cell == target { println!("b {:?}", leftref) };
|
||||||
|
if let Some(rightref) = rightref {
|
||||||
|
let right = grid.cells[rightref];
|
||||||
|
let righter = grid.right(rightref).map(|righterref| grid.cells[righterref]).unwrap_or(Colour::None);
|
||||||
|
//if cell == target { println!("{:?}, {:?}", right, righter) };
|
||||||
|
if right == righter {
|
||||||
|
if right != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(5);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match right {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_double_vertup(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let upref = grid.up(cell);
|
||||||
|
if let Some(upref) = upref {
|
||||||
|
let up = grid.cells[upref];
|
||||||
|
let upper = grid.up(upref).map(|upperref| grid.cells[upperref]).unwrap_or(Colour::None);
|
||||||
|
if up == upper {
|
||||||
|
if up != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(6);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match up {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_double_vertdown(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let downref = grid.down(cell);
|
||||||
|
if let Some(downref) = downref {
|
||||||
|
let down = grid.cells[downref];
|
||||||
|
let downer = grid.down(downref).map(|downerref| grid.cells[downerref]).unwrap_or(Colour::None);
|
||||||
|
if down == downer {
|
||||||
|
if down != Colour::None {
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(7);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
}
|
||||||
|
return match down {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => Colour::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
let cellrow = rows[cell / grid.dimension];
|
||||||
|
let ncount = cellrow.iter().filter(|e| **e == Colour::None).count();
|
||||||
|
if ncount != 2 {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
'outer: for row in rows {
|
||||||
|
if std::ptr::eq(row, cellrow) {
|
||||||
|
continue;
|
||||||
|
* */
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
let cindex = cell / grid.dimension;
|
||||||
|
let cellrow = rows[cindex];
|
||||||
|
let ncount = cellrow.iter().filter(|e| **e == Colour::None).count();
|
||||||
|
if ncount != 2 {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
'outer: for (i, row) in rows.iter().enumerate() {
|
||||||
|
if i == cindex {
|
||||||
|
*/
|
||||||
|
|
||||||
|
fn test_matching_row(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let rows = grid.as_rows();
|
||||||
|
let cellrow = &rows[cell / grid.dimension];
|
||||||
|
let ncount = cellrow.iter().filter(|e| **e == Colour::None).count();
|
||||||
|
if ncount != 2 {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
'outer: for row in &rows {
|
||||||
|
if row == cellrow {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..grid.dimension {
|
||||||
|
let current = cellrow[i];
|
||||||
|
let against = row[i];
|
||||||
|
if current != Colour::None && current != against {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_none = cellrow.iter().position(|e| *e == Colour::None).unwrap();
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(8);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return match row[first_none] {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => { println!("{:?}", row); println!("{:?}", cellrow); println!("{}", first_none); unreachable!()},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_matching_col(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let cols = grid.as_cols();
|
||||||
|
let cellcol = &cols[cell % grid.dimension];
|
||||||
|
let ncount = cellcol.iter().filter(|e| **e == Colour::None).count();
|
||||||
|
if ncount != 2 {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
'outer: for col in &cols {
|
||||||
|
if col == cellcol {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..grid.dimension {
|
||||||
|
let current = cellcol[i];
|
||||||
|
let against = col[i];
|
||||||
|
if against == Colour::None {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
if current != Colour::None && current != against {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_none = cellcol.iter().position(|e| *e == Colour::None).unwrap();
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(9);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return match col[first_none] {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => unreachable!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}
|
||||||
|
/**fn test_matching_col(grid: &Grid, cell: usize, trace: &mut u8, secondary_trace: &mut Vec<usize>) -> Colour {
|
||||||
|
let cellcol = grid.cells.iter().skip(col).step_by(grid.dimension).collect::<Vec<_>>();
|
||||||
|
let ncount = cellcol.iter().filter(|e| **e == Colour::None).count();
|
||||||
|
if ncount != 2 {
|
||||||
|
return Colour::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
'outer: for col in 0..grid.dimension {
|
||||||
|
if col == cellcol {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx, i) in grid.cells.iter().skip(col).step_by(grid.dimension).enumerate() {
|
||||||
|
let against = i;
|
||||||
|
if *against == Colour::None {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let current = cellcol[i];
|
||||||
|
if current != Colour::None && current != against {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_none = cellcol.iter().position(|e| *e == Colour::None).unwrap();
|
||||||
|
*trace += 1;
|
||||||
|
secondary_trace.push(9);
|
||||||
|
secondary_trace.push(cell);
|
||||||
|
return match col[first_none] {
|
||||||
|
Colour::Yellow => Colour::Blue,
|
||||||
|
Colour::Blue => Colour::Yellow,
|
||||||
|
Colour::None => unreachable!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Colour::None
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
pub struct ListNode {
|
||||||
|
pub val: i32,
|
||||||
|
pub next: Option<Box<ListNode>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListNode {
|
||||||
|
#[inline]
|
||||||
|
fn new(val: i32) -> Self {
|
||||||
|
ListNode {
|
||||||
|
next: None,
|
||||||
|
val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
|
||||||
|
let mut res = vec![];
|
||||||
|
|
||||||
|
let mut p1 = l1;
|
||||||
|
let mut p2 = l2;
|
||||||
|
let mut rollover = false;
|
||||||
|
loop {
|
||||||
|
if p1.is_none() && p2.is_none() {
|
||||||
|
if rollover {
|
||||||
|
res.push(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let v1;
|
||||||
|
if let Some(p1u) = p1 {
|
||||||
|
v1 = p1u.val;
|
||||||
|
p1 = p1u.next;
|
||||||
|
} else {
|
||||||
|
v1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let v2;
|
||||||
|
if let Some(p2u) = p2 {
|
||||||
|
v2 = p2u.val;
|
||||||
|
p2 = p2u.next;
|
||||||
|
} else {
|
||||||
|
v2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut nw = v1 + v2;
|
||||||
|
if rollover {
|
||||||
|
nw += 1;
|
||||||
|
rollover = false;
|
||||||
|
}
|
||||||
|
if nw > 9 {
|
||||||
|
nw -= 10;
|
||||||
|
rollover = true;
|
||||||
|
}
|
||||||
|
res.push(nw);
|
||||||
|
|
||||||
|
// if res.val == -1 {
|
||||||
|
// res = Box::new(npr);
|
||||||
|
// last = ⊀
|
||||||
|
// } else {
|
||||||
|
// # let mut o = Box::new(ListNode::new(nextp));
|
||||||
|
// # last.next = Some(o);
|
||||||
|
// # last = &mut o;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
let mut prev: Option<Box<ListNode>> = None;
|
||||||
|
for i in res.into_iter().rev() {
|
||||||
|
let mut np = ListNode::new(i);
|
||||||
|
np.next = prev;
|
||||||
|
prev = Some(Box::new(np));
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue