休日の調べもの

調べものをしたときのメモ

イラストロジックをだいたい解けるプログラム

#
import array

class ImageBoard:
    board=
    x_size=0
    y_size=0
    def __init__(self,xs,ys):
        self.x_size=xs
        self.y_size=ys
        for i in range(self.y_size):
            line=[0]*self.x_size
            self.board.append(line)
    def dump(self):
        for y in range(self.y_size):
            for x in range(self.x_size):
                if(self.board[y][x]==0):
                    print("?",end="")
                elif(self.board[y][x]==1): #fill
                    print("#",end="")
                else:
                    print("X",end=""#space
            print("")
    def get_rows(self,y):
        return self.board[y]
    def set_rows(self,y,row):
        for i in range(x_size):
            if(self.board[y][i]==0):
                self.board[y][i]=row[i]
    def get_cols(self,x):
        ret=[0]*x_size
        for i in range(y_size):
            ret[i]=self.board[i][x]
        return ret
    def set_cols(self,x,col):
        for i in range(y_size):
            if(self.board[i][x]==0):
                self.board[i][x]=col[i]

#
# 与えられた空白の数を隙間のに割り当てる
# 隙間の数の組み合わせを作る
# 1が黒、2が白
# 例)
#  □■■□□■■□■■□
#  2,1,1,2,2,1,1,2,1,1,2
#
# yield を使うともっと簡潔に書けるかも
#
# num 割り振る値の合計値
# cell_cnt 割り振る場所の数

def combination_generator(num,cell_cnt):
    ans=
    max_num=num-cell_cnt
    if(cell_cnt==1):
        ans.append([num])
    elif(cell_cnt==2):
        for i in range(max_num+1):
            ans.append([max_num+1-i,i+1])
    else:
        for i in range(1,max_num+2):
            ans_list=combination_generator(num-i,cell_cnt-1)
            for l in ans_list:
                ans.append([i]+l)
    return ans

#
# 列が指定の条件を満たしているか
# 0=未定 なら何でもよい
# その他は 1,2が一致している
#
#
def check_rows(target_cells,test_cells):
    flag=True
    for i in range(len(target_cells)):
        if(target_cells[i]>0 and target_cells[i]!=test_cells[i]):
            flag=False
    return flag
#
#
# 両サイドのエッジは0 ~ 最大自由度
# セルの中身は両サイドの自由度を引いた後が最大、最低が隙間の数。
#
def make_fill_pattern(target_cells,clue):
    match_patterns=
    cell_cnt=len(target_cells) #長さ
    num_cnt =len(clue) #数字の数
    num_sum =sum(clue) #リストの数字の合計
    if(cell_cnt==num_sum):
        match_patterns.append([1]*cell_cnt)
    elif(num_sum==0):
        match_patterns.append([2]*cell_cnt)
    else:
        space_cnt=cell_cnt-(num_sum+num_cnt-1#調整可能な空白
        vacant_cell_cnt=num_cnt-1 #隙間の数
        #print(cell_cnt,num_cnt,num_sum,space_cnt,vacant_cell_cnt)    
        if vacant_cell_cnt==0:#途中に空白がない場合
            for lc in range(space_cnt+1):                
                rc=space_cnt-lc
                candidate=[2]*lc+[1]*num_sum+[2]*rc
                if check_rows(target_cells,candidate):
                    match_patterns.append(candidate)
        else:
            for lc in range(space_cnt+1):  #左右の隙間を確保
                for rc in range(space_cnt-lc+1):
                    patterns=
                    usable_space_cnt=cell_cnt-lc-rc-num_sum
                    space_patterns=combination_generator(usable_space_cnt,vacant_cell_cnt)
                    for p in space_patterns:
                        p.extend([0]) #ループの最後対策
                        candidate=[]
                        for m in clue:
                            candidate.extend([1]*m)
                            candidate.extend([2]*p.pop(0))
                        candidate=[2]*lc+candidate+[2]*rc #比較候補
                        if check_rows(target_cells,candidate):
                            match_patterns.append(candidate)
    return match_patterns
#
# 1次元配列のtarget_cellsに対して、clue(ヒント)を満たす候補をすべて求めて比較
#候補が1つしかなければ決定
#全てセルで同じ結果になるのであれば、そのセルは決定
#縦のセルは1次元で横にして渡す
#
def think_by_line(target_cells,clue):
    cell_cnt=len(target_cells)
    if target_cells.count(0)==0:
        return [0]*cell_cnt #この列は決定している
    patterns=make_fill_pattern(target_cells,clue)
    if len(patterns)==1:
        fill_ptn=patterns[0]
    else:
        fill_ptn=[0]*cell_cnt
        for p in patterns:
            for i in range(cell_cnt):
                if(fill_ptn[i]==0):
                    fill_ptn[i]=p[i]
                elif(fill_ptn[i]!=p[i]):
                    fill_ptn[i]=3
        for i in range(cell_cnt):
            if( (target_cells[i]>0 and target_cells[i]!=fill_ptn[i]) or fill_ptn[i]==3):
                fill_ptn[i]=0
    return fill_ptn                
#
# パズルを解く本体 上から下まで横一列を解いた後、左から右に縦1列を解く
# 一通りやって、変更したセルがなくなったら終了
# 30x30でも5回ぐらいで解ける
#
def solve_main(x_size,y_size,max_challenge):
    for i in range(max_challenge):
        chg=0
        print"%d times try "%(i+1))
        for y in range(y_size):
            line=ib.get_rows(y)
            ret=think_by_line(line,row_clue[y])
            ib.set_rows(y,ret)
            chg += len(ret)-ret.count(0)
        for x in range(0,x_size):
            line=ib.get_cols(x)
            ret=think_by_line(line,col_clue[x])
            ib.set_cols(x,ret)
            chg += len(ret)-ret.count(0)
        if(chg==0):
            return True
    return False
            
if __name__ == "__main__":
    #問題をここに書く
    col_clue=[[2],[4],[6],[8],[8],[6],[4],[2]]
    row_clue=[[2],[4],[6],[8],[8],[6],[4],[2]]
    max_challenge=8
    x_size=len(col_clue)
    y_size=len(row_clue)
    print(x_size,y_size)
    ib=ImageBoard(x_size,y_size)
    if(solve_main(x_size,y_size,max_challenge)):
        print("Solved")
    else:
        print("Give Up!")
    ib.dump()

Slim がバージョンが上がるごとにデブっていく

最初は何にもないルーティングだけのSlimが2019年9月にリリースされたSlim4はかなりいろいろついてる。付加機能は余分な脂肪と言えなくもないが、エラーハンドラとかユニットテストとか、結局作るんでしょといったものがSkeltonで用意されているのはうれしい。

とりあえず、composerでslimをインストールしたら、下記コマンドでskeltonもインストールする

composer create-project slim/slim-skeleton [ProjectName]

現時点ではSlim4に対応した日本語解説はないので、自力で構造を調べる。

src
├── Application
│   ├── Actions
│   │   ├── ActionError.php
│   │   ├── ActionPayload.php
│   │   ├── Action.php
│   │   └── User  
│   │           ├── ListUsersAction.php
│   │           ├── UserAction.php
│   │           └── ViewUserAction.php
│   ├── Handlers
│   │      ├── HttpErrorHandler.php
│   │      └── ShutdownHandler.php
│   ├── Middleware
│   │      └── SessionMiddleware.php
│   └── ResponseEmitter
│           └── ResponseEmitter.php
├── Domain
│   ├── DomainException
│   │      ├── DomainException.php
│   │      └── DomainRecordNotFoundException.php
│   └── User
│           ├── UserNotFoundException.php エラー処理
│           ├── User.php
│           └── UserRepository.php
└── Infrastructure
        └── Persistence
                 └── User
                        └── InMemoryUserRepository.php サンプルのデータ固定配列
app
├── dependencies.php
├── middleware.php セッション管理などをする
├── repositories.php
├── routes.php        リクエストルーティングする コマンド追加時に変更する
└── settings.php


public
└── index.php

 

Skeltonは、ユーザーデータの住所録なので自分のデータを取り扱わせるためにはUserのところを順次いじっていけばいい。まずはInfrastructure以下のデータの持ち方を変える。

routes.php はパラメータなしで呼ばれたときはHello Worldを簡単なhtmlで返す。コマンドを作りたい場合は下のgroup使ってパラメータにより分岐させる。まあ、すっきり。Userの最初の入り口もここになる。

 

機械学習とかを手早く試したい

 機械学習を試しながら覚えようと思っても、実行環境の構築が大変すぎる。特に進化のスピードが速すぎて、1年前の記事とか参考になるどころか依存性地獄にはまり込む罠だったりする。

 土日を丸々つぶして環境を構築したらもう力尽きてしまって、本来の目的が何だったか忘れる。

 

 そんな時はGoogleさんのColaboratory。Google Driveで[新規]->[Colaboratory] はいJupyter Notebook 。!でシェルコマンドを実行することができるので、足りないモジュールはpipで入れる。 googleドライブもマウントできるので、データーの入出力も困らない。 Googleさんの手のひらでコロコロしている感じは否めないが、練習だったらもう十分。

 

参考にしたページ

qiita.com

 

DES暗号

DESです

python 

import pyDes;
des = pyDes.des('01234567',pyDes.CBC,"\0\0\0\0\0\0\0\0");
print des.encrypt('12345678').encode('hex')

PHP

<?php

$key = "01234567";
$str = "12345678";
$iv = hex2bin("0000000000000000");

$encrypt = openssl_encrypt($str,'des-cbc',$key,OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING ,$iv);
$a=bin2hex($encrypt);
print $a;

 

3DESです

python

import pyDes

# 2 Key 3 DES ENCODE
data = "12345678"
des = pyDes.des('01234567',pyDes.CBC,"\0\0\0\0\0\0\0\0")
a=des.encrypt(data)
des2 = pyDes.des('76543210',pyDes.CBC,"\0\0\0\0\0\0\0\0")
b=des2.decrypt(a)
des3 = pyDes.des('01234567',pyDes.CBC,"\0\0\0\0\0\0\0\0")
c=des3.encrypt(b)
print c.encode('hex')


# Functional Equivalent 上記を1行で書く
k = pyDes.triple_des("0123456776543210", pyDes.CBC , "\0\0\0\0\0\0\0\0")
d = k.encrypt(data)
print d.encode('hex')

 

PHP

<?php

$key = "0123456776543210";
$str = "12345678";
$iv = hex2bin("0000000000000000");

$encrypt = openssl_encrypt($str,'des-ede-cbc',$key,OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING ,$iv);
$a=bin2hex($encrypt);
print $a;