add scripts, the start of a monte-carlo
This commit is contained in:
parent
1b55a9c1e4
commit
e5c655eafb
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.idea/
|
||||||
|
*.py[co]
|
||||||
|
__pycache__/
|
||||||
|
*~
|
1
montecarlo/rummicube/.gitignore
vendored
Normal file
1
montecarlo/rummicube/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
target/
|
6
montecarlo/rummicube/Cargo.lock
generated
Normal file
6
montecarlo/rummicube/Cargo.lock
generated
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "rummicube"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
7
montecarlo/rummicube/Cargo.toml
Normal file
7
montecarlo/rummicube/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "rummicube"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Artemis Tosini <me@artem.ist>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
2
montecarlo/rummicube/src/iteration.rs
Normal file
2
montecarlo/rummicube/src/iteration.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
use crate::tile::*;
|
||||||
|
|
13
montecarlo/rummicube/src/main.rs
Normal file
13
montecarlo/rummicube/src/main.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![allow(unused_imports, unused_variables, dead_code)]
|
||||||
|
|
||||||
|
mod player;
|
||||||
|
mod tile;
|
||||||
|
mod iteration;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
use crate::player::*;
|
||||||
|
use crate::tile::*;
|
||||||
|
|
||||||
|
fn main() {}
|
0
montecarlo/rummicube/src/player.rs
Normal file
0
montecarlo/rummicube/src/player.rs
Normal file
35
montecarlo/rummicube/src/tests.rs
Normal file
35
montecarlo/rummicube/src/tests.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
use crate::tile::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_trivial_run() {
|
||||||
|
let tiles: Vec<NormalTile> = (1..=MIN_GROUP_SIZE)
|
||||||
|
.map(|i| NormalTile::new(TileColor::Blue, i as u32))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let groups = find_groups(&tiles.iter().map(|n| Tile::Normal(*n)).collect());
|
||||||
|
let expected = vec![Group::new(GroupType::Run, tiles)];
|
||||||
|
assert_eq!(groups, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_5_run() {
|
||||||
|
let tiles: Vec<NormalTile> = (1..=5)
|
||||||
|
.map(|i| NormalTile::new(TileColor::Blue, i as u32))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let groups = find_groups(&tiles.iter().map(|n| Tile::Normal(*n)).collect());
|
||||||
|
let expected = vec![Group::new(GroupType::Run, tiles)];
|
||||||
|
assert_eq!(groups, expected)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_too_short_run() {
|
||||||
|
let tiles: Vec<NormalTile> = (1..=2)
|
||||||
|
.map(|i| NormalTile::new(TileColor::Blue, i as u32))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let groups = find_groups(&tiles.iter().map(|n| Tile::Normal(*n)).collect());
|
||||||
|
let expected = vec![];
|
||||||
|
assert_eq!(groups, expected)
|
||||||
|
}
|
179
montecarlo/rummicube/src/tile.rs
Normal file
179
montecarlo/rummicube/src/tile.rs
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
pub(crate) const MAX_TILE: u32 = 13;
|
||||||
|
pub(crate) const NUM_WILDCARDS: u32 = 2;
|
||||||
|
pub(crate) const NUM_COPIES: u32 = 2;
|
||||||
|
pub(crate) const MIN_GROUP_SIZE: u32 = 3;
|
||||||
|
pub(crate) const COLORS: [TileColor; 4] = [
|
||||||
|
TileColor::Blue,
|
||||||
|
TileColor::Black,
|
||||||
|
TileColor::Red,
|
||||||
|
TileColor::Orange,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub(crate) enum TileColor {
|
||||||
|
Blue,
|
||||||
|
Black,
|
||||||
|
Red,
|
||||||
|
Orange,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub(crate) struct NormalTile {
|
||||||
|
color: TileColor,
|
||||||
|
value: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NormalTile {
|
||||||
|
pub(crate) fn new(color: TileColor, value: u32) -> NormalTile {
|
||||||
|
NormalTile { color, value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub(crate) enum Tile {
|
||||||
|
Normal(NormalTile),
|
||||||
|
Wildcard,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Tile> for Option<NormalTile> {
|
||||||
|
fn from(t: Tile) -> Self {
|
||||||
|
match t {
|
||||||
|
Tile::Normal(n) => Some(n),
|
||||||
|
Tile::Wildcard => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub(crate) enum GroupType {
|
||||||
|
Run,
|
||||||
|
Colors,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
|
pub(crate) struct Group {
|
||||||
|
typ: GroupType,
|
||||||
|
tiles: Vec<NormalTile>,
|
||||||
|
count: u32,
|
||||||
|
sum: u32,
|
||||||
|
}
|
||||||
|
impl Group {
|
||||||
|
pub(crate) fn new(typ: GroupType, tiles: Vec<NormalTile>) -> Group {
|
||||||
|
Group {
|
||||||
|
typ,
|
||||||
|
tiles: tiles.clone(),
|
||||||
|
count: tiles.len() as u32,
|
||||||
|
sum: tiles.iter().map(|tile| tile.value).sum(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) fn all_tiles() -> Vec<Tile> {
|
||||||
|
let mut tiles = COLORS
|
||||||
|
.iter()
|
||||||
|
.flat_map(|color| build_run(color.clone(), (1..(MAX_TILE + 1)).collect()))
|
||||||
|
.map(|normal_tile| Tile::Normal(normal_tile))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let orig_tiles = tiles.clone();
|
||||||
|
|
||||||
|
for _ in 1..NUM_COPIES {
|
||||||
|
tiles.append(&mut orig_tiles.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
tiles.append(
|
||||||
|
&mut std::iter::repeat(Tile::Wildcard)
|
||||||
|
.take(NUM_WILDCARDS as usize)
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
|
||||||
|
tiles
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_run(color: TileColor, values: Vec<u32>) -> Vec<NormalTile> {
|
||||||
|
values
|
||||||
|
.iter()
|
||||||
|
.map(|value| NormalTile {
|
||||||
|
color,
|
||||||
|
value: *value,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_instance<I: PartialEq>(vec: &mut Vec<I>, item: I) {
|
||||||
|
if let Some(idx) = vec.iter().position(|it| *it == item) {
|
||||||
|
vec.remove(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_tiles(tiles: &mut Vec<NormalTile>, run: Vec<NormalTile>) {
|
||||||
|
for tile in run {
|
||||||
|
remove_instance(tiles, tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn find_groups(tiles: &Vec<Tile>) -> Vec<Group> {
|
||||||
|
// Note that this is a greedy algorithm, so it is non-optimal.
|
||||||
|
// Hopefully the difference isn't too big
|
||||||
|
|
||||||
|
let mut groups = Vec::new();
|
||||||
|
let mut tiles_left: Vec<NormalTile> = tiles
|
||||||
|
.iter()
|
||||||
|
.filter_map(|tile| Option::from(*tile))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for color in &COLORS {
|
||||||
|
let mut tile_numbers: Vec<_> = tiles_left
|
||||||
|
.iter()
|
||||||
|
.filter_map(|tile| {
|
||||||
|
if tile.color == *color {
|
||||||
|
Some(tile.value)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
tile_numbers.sort_unstable();
|
||||||
|
|
||||||
|
if let Some(min_tile) = tile_numbers.first() {
|
||||||
|
let mut i = *min_tile;
|
||||||
|
let mut current_group = Vec::new();
|
||||||
|
while i <= MAX_TILE {
|
||||||
|
if tile_numbers.contains(&i) {
|
||||||
|
current_group.push(i);
|
||||||
|
} else if current_group.len() as u32 >= MIN_GROUP_SIZE {
|
||||||
|
let run = build_run(*color, current_group.clone());
|
||||||
|
groups.push(Group::new(GroupType::Run, run.clone()));
|
||||||
|
remove_tiles(&mut tiles_left, run.clone());
|
||||||
|
|
||||||
|
current_group.clear();
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next find the groups of different colors
|
||||||
|
|
||||||
|
for i in 1..=MAX_TILE {
|
||||||
|
let mut tiles = Vec::new();
|
||||||
|
for color in &COLORS {
|
||||||
|
let tile = NormalTile {
|
||||||
|
color: color.clone(),
|
||||||
|
value: i,
|
||||||
|
};
|
||||||
|
if tiles_left.contains(&tile) {
|
||||||
|
tiles.push(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tiles.len() as u32 >= MIN_GROUP_SIZE {
|
||||||
|
groups.push(Group::new(GroupType::Colors, tiles.clone()));
|
||||||
|
remove_tiles(&mut tiles_left, tiles.clone());
|
||||||
|
tiles.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
groups.clone()
|
||||||
|
}
|
9
scripts/ykclip-menu.sh
Executable file
9
scripts/ykclip-menu.sh
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
name=$(ykman oath list | wofi -k /dev/null -i -d)
|
||||||
|
|
||||||
|
line=$(ykman oath code $name | head -n 1)
|
||||||
|
if test -n "$line"
|
||||||
|
then
|
||||||
|
echo $line | awk '{print $NF}' | wl-copy
|
||||||
|
fi
|
Loading…
Reference in a new issue