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