Sass基本

### Sassの特徴
– ネスト構造を利用できる
– スタイルシートを分けられる
– 条件分岐を利用できる
– mixin機能の利用

### 変数

$black: #000000;
$position: left;

.item1 {
    color: $black;
}

.item2 {
    background: $black;
    margin-#{$position}: 30px;
}

$black: #000000;
$position: left;

.item1 {
    color: $black;
}

.item2 {
    background: $black;
    margin-#{$position}: 30px;
}

### ネスト

.item1 {
    width: 200px;

    .item2 {
        width: 100px;

        .item3 {
            width: 50px;
        }
    }
}

.item1 {
    width: 200px;

    .item2 {
        width: 100px;

        .item3 {
            width: 50px;
        }
    }
}

### 条件分岐

$position: left;
$width: 250px;

.item1 {
    @if $position == left {
        padding-left: 10px;
    }
}

.item2 {
    @if $width > 300px {
        margin-right: 10px;
    } @else if $width < 200px {
        margin-left: 10px;
    } @else {
        margin-top: 10px;
    }
}

.item1 {
  padding-left: 10px;
}

.item2 {
  margin-top: 10px;
}

break pointの時に利用したいですね。

gulpでjsの圧縮

$ mkdir gulp_js
$ cd gulp_js
$ npm init -y

$ npm install -D gulp
$ npm install -D gulp-uglify
$ npm install -D gulp-rename

gulpfile.js

var gulp = require("gulp");
var rename = require("gulp-rename");
var uglify = require("gulp-uglify");

gulp.task("default", function(){
    gulp.src('src/something.js')
        .pipe(uglify())
        .pipe(rename({
            extname: '.min.js'
        }))
        .pipe(gulp.dest('dest/'));
    done();
});

something.min.js

console.log("hello world!"),console.log("hello world! 2");

minifyされていることが確認できます。
一旦はSassだけでスタートして、JSは後からやりますか…

gulpの初期設定(gulpfile.js)

$ npm init -y
// gulpのインストール
$ npm install gulp –save-dev

gulpfile.js

const gulp = require('gulp');

gulp.task('default', function(){
    console.log('Gulp is running');
});

### sassの導入
$ npm install –save-dev gulp-sass sass

const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));

gulp.task('default', function(){
    console.log('Gulp is running');
    done();
});

gulp.task('sass', function() {
    return gulp.src('dev/scss/**/*.scss')
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('dist/css'));
});

gulp.task('default', gulp.series('sass'));
$primary-color: #333;

body {
    color: $primary-color;
}

$ npx gulp

cssファイルはできるんだけど、サーバを動かしながら見たいな…

【Rust】○✖️ゲーム(minmax)

use rand::Rng;
use std::cmp::Ordering;

static goal:[i32; 8] = [ 0b111000000, 0b000111000, 0b000000111, 0b100100100,
            0b010010010, 0b001001001, 0b100010001, 0b001010100];

fn check(player: i32) -> bool {
    for mask in goal {
        if player & mask == mask {
            return true
        }
    }
    return false 
}

fn minmax(p1: i32, p2: i32, turn: bool) -> i32 {
    if check(p2) {
        if turn {
            return 1
        } else {
            return -1
        }
    }
    let board: i32 = p1 | p2;
    if board == 0b111111111{
        return 0
    }

    let mut w = Vec::new();
    for i in 0..9 {
        if board & (1 << i) == 0 {
            w.push(i);
        }
    }

    let mut k = Vec::new();
    if turn {
        for i in w {
           k.push(minmax(p2, p1 | (1 << i), !turn))
        }
        return *k.iter().min().unwrap();
    } else {
        for i in w {
            k.push(minmax(p2, p1 | (1 << i), !turn))
        }
        return *k.iter().max().unwrap();
    }
    

}

fn play(p1: i32, p2: i32, turn: bool) {
    if check(p2) {
        println!("{:09b}, {:09b}", p1, p2);
        return
    } 

    let board: i32 = p1 | p2;
    if board == 0b111111111{
        println!("{:09b}, {:09b}", p1, p2);
        return
    }
    let mut w = Vec::new();
    for i in 0..9 {
        if board & (1 << i) == 0 {
            w.push(i);
        }
    }

    let mut r  = Vec::new();
    for i in w.clone() {
        r.push(minmax(p2, p1 | (1 << i), true))
    }
    let n = r.iter()
        .enumerate()
        .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal))
        .map(|(index, _)| index).unwrap();
    let j = w[n];
    play(p2, p1 | (1 << j), !turn);
}

fn main() {
    play(0, 0, true);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.32s
Running `target/debug/rust`
001110010, 110001101

う、なんか違うな…

    let mut rnd = rand::thread_rng();
    let k = rnd.gen_range(1..n);
    let j = w[k];

このようにすると、ランダム性が出る。。

【Rust】○✖️ゲーム

マスを0と1で表現して、2進法の加算で判定する。

fn main() {

    println!("{:09b}", 0b111000000 & 0b000111111);
    println!("{:09b}", 0b111000000 & 0b101100010);
    println!("{:09b}", 0b111000000 & 0b111000010);
}

000000000
101000000
111000000

ちなみに、0b111000000など2進数の型はi32

use rand::Rng;

static goal:[i32; 8] = [ 0b111000000, 0b000111000, 0b000000111, 0b100100100,
            0b010010010, 0b001001001, 0b100010001, 0b001010100];

fn check(player: i32) -> bool {
    for mask in goal {
        if player & mask == mask {
            return true
        }
    }
    return false 
}

fn play(p1: i32, p2: i32) {
    if check(p2) {
        println!("{:09b}, {:09b}", p1, p2);
        return
    } 

    let board: i32 = p1 | p2;
    if board == 0b111111111{
        println!("{:09b}, {:09b}", p1, p2);
        return
    }
    let mut w = Vec::new();
    for i in 0..9 {
        if board & (1 << i) == 0 {
            w.push(i);
        }
    }
    let n = w.len() + 1;
    let mut rnd = rand::thread_rng();
    let r = rnd.gen_range(1..n);
    play(p2, p1 | (1 << r));
}

fn main() {
    play(0, 0);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.30s
Running `target/debug/rust`
010001000, 001111000

これはさっぱりわからん…

【Rust】指定パスのファイル、ディレクトリを取得(depth & linear)

ファイル、フォルダの取得
fs::read_dir()がファイルの一覧取得

use std::error::Error;
use std::fs;
use std::path;

pub fn read_dir(path: &str) -> Result<Vec<path::PathBuf>, Box<dyn Error>>{
    let dir = fs::read_dir(path)?;
    let mut files: Vec<path::PathBuf> = Vec::new();
    for item in dir.into_iter() {
        files.push(item?.path());
    }
    Ok(files)
}


fn main() {
    let files = read_dir("./");
    println!("{:?}", files);
}

Compiling rust v0.1.0 (/home/vagrant/dev/algorithm/rust)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s
Running `target/debug/rust`
Ok([“./target”, “./.gitignore”, “./Cargo.lock”, “./Cargo.toml”, “./.git”, “./src”])

### 再帰的にディレクトリ内のファイルを取得

use std::error::Error;
use std::fs;
use std::path;

pub fn read_dir(path: &path::PathBuf) {
    let dir = fs::read_dir(path).unwrap();
    let mut files: Vec<path::PathBuf> = Vec::new();
    for item in dir.into_iter() {
        
        let name = item.unwrap().path();
        if name.is_dir() {
            read_dir(&name);
        } else {
            files.push(name);
        }
    }
    println!("{:?}", files);
}


fn main() {
    let path = path::PathBuf::from("./src");
    read_dir(&path);
}

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.20s
     Running `target/debug/rust`
["./src/test/test.rs"]
["./src/binary_search.rs", "./src/linear_search.rs", "./src/fibonacci.rs", "./src/tree_search.rs", "./src/main.rs", "./src/maze.rs", "./src/cardinal.rs", "./src/vending_machine.rs", "./src/fizzbuzz.rs", "./src/8queen.rs", "./src/prime.rs"]

これは感覚的に理解しやすいですね。

### 幅優先探索
再帰で検索するのではなく、ディレクトリをvectorに追加していき、各ディレクトリのファイルをそれぞれ取得していく。答えは同じだが、深さで検索するのではなく、対象を一つ一つ処理していくところが面白い。

fn main() {
    let mut queue: VecDeque<path::PathBuf> = VecDeque::new();
    queue.push_back("./src".into());
    let mut files: Vec<path::PathBuf> = Vec::new();

    while queue.len() > 0 {
        let path = queue.pop_front();
        let dir = fs::read_dir(path.unwrap()).unwrap();
        for item in dir.into_iter() {
            let name = item.unwrap().path();
            if name.is_dir() {
                queue.push_back(name);
            } else {
                files.push(name);
            }
        }
    }
    println!("{:?}", files);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.42s
Running `target/debug/rust`
["./src/binary_search.rs", "./src/linear_search.rs", "./src/fibonacci.rs", "./src/tree_search.rs", "./src/main.rs", "./src/maze.rs", "./src/cardinal.rs", "./src/vending_machine.rs", "./src/fizzbuzz.rs", "./src/read_dir.rs", "./src/8queen.rs", "./src/prime.rs", "./src/test/test.rs"]

【Rust】ハノイの塔

再起的なので、対象枚数が増えるほど、指数関数的に計算数が増えていく。

use std::env;

fn hanoi(n: i32, src: String, dist: String, via: String) { // n, 移動元、移動先、経由
    if n > 1 {
        hanoi(n - 1, src.clone(), via.clone(), dist.clone());
        println!("{} -> {}", src.clone(), dist.clone());
        hanoi(n - 1, via.clone(), dist.clone(), src.clone());
    } else {
        println!("{} -> {}", src.clone(), dist.clone());
    }

}

fn main() {
    let args: Vec<String> = env::args().collect();
    let n = args[1].parse::<i32>().unwrap();
    println!("入力値:{}", n);

    hanoi(n, "a".to_string(), "b".to_string(), "c".to_string());
}

Compiling rust v0.1.0 (/home/vagrant/dev/algorithm/rust)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s
Running `target/debug/rust 3`
入力値:3
a -> b
a -> c
b -> c
a -> b
c -> a
c -> b
a -> b

### 考察
3 a b c (a->b)
2 a c b (a->c)
1 a b c (a->b)
1 b c a (b->c)
3 a b c (a->b)
2 ….

【Rust】簡易的なBloomfilter

ブルームフィルタを更新していくロジックがいまいちわからんが、なんとなく

use std::hash::{DefaultHasher, Hash, Hasher};

#[derive(Debug, PartialEq, Clone)]
struct BloomFilter {
    filter: [i32; 10],
}

impl BloomFilter {
    fn set_v(&mut self, val: String) {
        let list: Vec<u8> = self.n_hash(val);
        for l in list {
            let i = usize::from(l);
            if self.filter[i] == 0 {
                self.filter[i] = 1
            } else {
                self.filter[i] = 2 }
        }    
    }

    fn n_hash(&self, val: String) -> Vec<u8>{
        let hashed = siphash(val);
        let list: Vec<u8> = s_digit(hashed);
        return list
    }

    fn check_v(self, val: String) -> bool {
        let list: Vec<u8> = self.n_hash(val);
        let mut c_bf = BloomFilter { filter: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]};
        for l in list {
            let i = usize::from(l);
            if c_bf.filter[i] == 0 {
                c_bf.filter[i] = 1
            } else {
                c_bf.filter[i] = 2 }
        }
        return self == c_bf
    }
}

fn siphash(s: String) -> u64 {
    let mut siphash = DefaultHasher::new();
    s.hash(&mut siphash);
    return siphash.finish()
}

fn s_digit(n: u64) -> Vec<u8> {
    n.to_string()
        .chars()
        .into_iter()
        .map(|char| char.to_digit(10).unwrap() as u8)
        .collect()
}

fn main(){
    let mut bf = BloomFilter { filter: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]};
    bf.set_v("hello world".to_string());
    println!("{:?}", bf);
    println!("{}", bf.clone().check_v("hello world!".to_string()));
    println!("{}", bf.clone().check_v("hello world".to_string()));
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.33s
Running `target/debug/wallet`
BloomFilter { filter: [2, 2, 0, 1, 2, 1, 1, 2, 2, 2] }
false
true

【Rust】DefaultHasherで文字列から数値型へ

何度やっても同じ値になります。使い勝手は良さそう。

use std::hash::{DefaultHasher, Hash, Hasher};

fn siphash13(s: String) {
    let mut siphash = DefaultHasher::new();
    s.hash(&mut siphash);
    println!("{:?}", siphash.finish());
    println!("{:?}", siphash);
}

fn main(){
    let mut t = "hello wolrd".to_string();
    siphash13(t);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35s
Running `target/debug/wallet`
397376489521336075
DefaultHasher(SipHasher13 { hasher: Hasher { k0: 0, k1: 0, length: 12, state: State { v0: 14783544211356068956, v2: 15472093343132851580, v1: 2669010635360672206, v3: 8002614515094862307 }, tail: 4284772972, ntail: 4, _marker: PhantomData } })