電波ビーチ

☆(ゝω・)v

さくらvps+debian+nginx+httpsでVirtualHost

さくらvpsの一番安いやつに入れていきます。

続きを読む

Goでスライスの任意のインデックスに挿入

ちなみに「任意のインデックスを削除」はこれでやってます。

or3.hatenablog.com

実装

package main
import "fmt"

func main(){
    n := []int{1, 2, 3,}
    incert_target := 9999
    intint := make([][]int, 0)
    for i:=0; i<len(n)+1; i++{
        intint = append(intint, incert(i, incert_target, n))
    }
    fmt.Println(intint)
}


func incert(index int, x int, origin []int)(ret []int){
    ret = append([]int{}, origin...)
    ret = append(ret[:index], append([]int{x}, ret[index:]...)...)
    return
}

Goのスライスの応用的な使い方はこれを一通りみればいいです

golang.shop

ちなみにdeleteはmapの組み込み関数なので注意。

Goで順列を辞書順で

スライスのポインタで渡すところとスライスのコピーとスライスの任意のインデックスの要素を消すっていう実装が頭まわりませんでした…

実装

package main
import "fmt"

func main(){
    test := []int{1, 2, 3, 4}
    perms := permuration(test, 3)
    fmt.Println("1から4の中から3つ取る順列")
    fmt.Println(perms)

    // int以外の場合でもどうせインデックスを返すので数列を渡せばいい
    aquars := []string{"千歌", "梨子", "曜", "ダイヤ", "果南", "鞠莉", "善子", "花丸", "ルビィ"}
    indices := make([]int, len(aquars))
    for i := 0; i<len(aquars); i++{
        indices[i] = i
    }
    coupling := permuration(indices,  3)
    for _, c := range coupling{
        for i, v := range c{
            fmt.Print(aquars[v])
            if i<2{
                fmt.Print(" x ")
            }
        }
        fmt.Println()
    }
}

func permuration(target []int, limit int)([][]int){
    if limit<1 || len(target)<limit{
        return nil
    }
    ret := make([][]int, 0)
    gen_perm(make([]int, 0), target, &ret, limit)
    return ret
}

func gen_perm(perm []int, rest []int, lis *[][]int, n int){
    if n==0{
        *lis = append(*lis, perm)
    }else{
        // 探索
        for i, r := range rest{
            next_rest := make([]int, 0)
            next_rest = append(next_rest, rest...)
            next_perm := make([]int, 0)
            next_perm = append(next_perm, perm...)

            next_rest = deleteIndex(next_rest, i)
            next_perm = append(next_perm, r)
            gen_perm(next_perm, next_rest, lis, n-1)
        }

    }
}

func deleteIndex(in []int, index int)[]int{
    out := make([]int, 0)
    out = append(out, in...)
    if index<0 || len(in)<index{
        fmt.Println("delete index mis")
        return nil
    }
    out = append(out[:index], out[index+1:]...)
    return out
}

gen_perm は最初無名関数でやってたんですが無名関数の再帰ってできないんですね(当然)

参考

Go のスライスでハマッたところ - Block Rockin’ Codes

JavaScriptによる順列組み合わせの生成 - Qiita

http://antlers.cis.ibaraki.ac.jp/PROGRAM/CPROG/237.pdf

Goで「文字列のa番目からb番目までを反転」をやる

そういう問題があったので。

Transformation | Aizu Online Judge

func Reverse(s string, a int, b int) string {
    r := []rune(s)
    for i, j := a, b; i < (a+b)/2+1; i, j = i+1, j-1 {
        r[i], r[j] = r[j], r[i]
    }
    return string(r)
}

(a+b)/2+1でちゃんと+1しないといけない。

Goで二次元スライスの宣言をグローバルでやってローカルで初期化

日本語あってるかわかりませんが。
mainの外で二次元スライスを作っておき、中でmakeでcap/lenを設定して初期化するといいです。

package main
import "fmt"

var multislice [][]string

func main(){
    multislice = make([][]string, 4)
    s := []string{"ドバイ", "インド", "ドイツ", "味噌汁"}
    for i:=0; i<len(multislice); i++{
        multislice[i] = make([]string, 3)
        for j:=0; j<len(multislice[0]); j++{
            multislice[i][j] = string([]rune(s[i])[j])
        }
    }
    fmt.Println(multislice)
}

出力

[[ド バ イ] [イ ン ド] [ド イ ツ] [味 噌 汁]]

競プロでたとえば入力であとからHeight, Widthを与えられる問題なんかのときにどうすりゃいいかわからんかったので。

2次元配列のリストの中に特定の2次元配列が含まれているかどうかをいい感じに高速に判定するにはどうすればいいですか

むかし書いたやつが発掘されたので供養というか。すっかりC#忘れてるので読解に苦労しました。むかしの自分すげぇな

using System;
using System.Linq;
using System.Collections.Generic;

public class Program{
    public static void Main(){
        
        //はじめに
        var test1 = new int[,]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        var test2 = test1.Clone() as int[,];     //test1と同値をもつ2次元配列
        var set1 = new HashSet<int[,]>();
        set1.Add(test1);
        Console.WriteLine(set1.Contains(test2));    //test1とtest2はそもそも別オブジェクトなので当然
        
        var unziped1 = UnZip(test1);    //一次元配列に展開
        var unziped2 = UnZip(test2);    //同じく
        var set2 = new HashSet<int[]>();
        set2.Add(unziped1);
        Console.WriteLine(set2.Contains(unziped2));  //当然
        
        ///////////////////////////////////////////////////
        //解法1
        //値型に何らかの形で直してやるパターン
        //文字列
        var str1 = ToStr(test1);
        var str2 = ToStr(test2);
        var set3 = new HashSet<string>();
        set3.Add(str1);
        Console.WriteLine(set3.Contains(str2));     //文字列に直せばいいけどstringへの変換がクソ遅い
        
        //longとかそのへん
        var longed1 = ToLong(test1);
        var longed2 = ToLong(test2);
        var set4 = new HashSet<long>();
        set4.Add(longed1);
        Console.WriteLine(set4.Contains(longed2));  //文字列よりはマシだけど一桁ずつに情報をもたせているので9種類しか持てないし限定的すぎる(1と11が含まれていたらもう復元できない・0が先頭になることはない)
                                                    //あるいは数値とインデックスでHashCode的なのをうまく一意に生成できれば可能っぽいけど
        
        //////////////////////////////////////////////////
        //解法2
        //愚直に舐めていくパターン
        set1.Clear();
        bool flag;
        var _any1 = new int[,]{{2, 3, 4}, {5, 6, 7}, {8, 9, 1}};
        var _any2 = new int[,]{{3, 4, 5}, {6, 7, 8}, {9, 1, 2}};
        var _any3 = new int[,]{{9, 8, 7}, {6, 5, 4}, {3, 2, 1}};
        //...このあと_any1000000000くらいまで続くと想定
        set1.Add(_any1);
        set1.Add(_any2);
        set1.Add(_any3);
        //...このあと_any1000000000くらいまで続く想定
        set1.Add(test1);
        
        //set1にtest2と同じ要素をもつものが含まれているかどうか調べたい
        var b = false;
        foreach(var s in set1){
            if(Check(s, test2)){
                b = true;
                break;
            }
        }
        Console.WriteLine(b ? "ありました" : "ねぇよ帰れクソが");
        //この方法だと見つけたいターゲットがリストの最後のほうにあったときに探索に時間がかかる。Linqもゴテゴテなのでたぶん遅い
    }
    
    public static int[] UnZip(int[,] moto){
        return moto.Cast<int>().ToArray();
        var h = moto.GetLength(0);
        var w = moto.GetLength(1);
        var len = h*w;
        var ret = new int[len];
        for(int i=0; i<h; i++){
            for(int j=0; j<w; j++){
                ret[i*w+j] = moto[i,j];
            }
        }
        return ret;
    }
    
    public static string ToStr(int[,] moto){
        var h = moto.GetLength(0);
        var w = moto.GetLength(1);
        var sb = new System.Text.StringBuilder();
        for(int i=0; i<h; i++){
            for(int j=0; j<w; j++){
                sb.Append(moto[i,j].ToString());
            }
        }
        return sb.ToString();
    }
    
    public static long ToLong(int[,] moto){
        var h = moto.GetLength(0);
        var w = moto.GetLength(1);
        long ret = default(long);
        for(int i=0; i<h; i++){
            for(int j=0; j<w; j++){
                var count = i*h+j;
                ret+=moto[i,j]*(long)Math.Pow(10, h*w-count-1);
            }
        }
        return ret;
    }
    
    
    public static bool Check(int[,] me, int[,] target){
        //meとtargetが同じ次元数かつ同じ要素数であるか
        var unko = me.Rank==target.Rank&&Enumerable.Range(0, me.Rank).All(dim=>me.GetLength(dim)==target.GetLength(dim));
        if(!unko) return false;
        return me.Cast<int>().SequenceEqual(target.Cast<int>());
    }
}

Debian環境をつくる さくらVPS編

or3.hatenablog.com

結局さくらで構築することになった。。以前やったこれとまったく同じことをやります

導入

VPS(仮想専用サーバー)|さくらインターネット - 無料お試し実施中 一番安いプラン。クレジットカードがあれば二週間無料で使えるらしい。

OSインストール

さくらVPSの設定ページからサーバ情報 -> 各種設定 -> OSインストール -> カスタムOSでDebian9を選択。自前でイメージを用意する必要すらないので楽。用意ができたらシリアルコンソールで設定。VNCコンソールは頻繁にフリーズするし画面移動もできないし使いにくい。

Config

だいたい今までと同じ。いちおう流れをおさらいすると

  1. apt-get update
  2. apt-get installsudosshvim
  3. adduserでユーザー追加、そのユーザーにsudo権限を与えておく。adduser <username> sudoとかでいける なんかうまくいかなくなってた? useradd <username> したあとに gpasswd -a <username> wheel してsudo権限を与えて、 passwd <username> でパスワードを作ってみた。
  4. Mac側でssh公開鍵/秘密鍵のペア作成。ssh-keygen -t rsa -b 4096 -f .ssh/{file_name_of_key}とかでいい
  5. scpとかssh-copy-idとか好きな方法で公開鍵を送る。ssh-copy-idを使う場合はssh-copy-id -i .ssh/{file_name_of_key} -p {port number} {target_name}@{target_host}とかにする。Permission Deniedとか言われる場合はホストの/etc/ssh/sshd_configの設定を疑う。最初に接続する場合はもちろんPasswordAuthenticationyesにしないと鍵すら送れない。送ったらちゃんとnoにしておく。あとポート番号もちゃんとしといたほうがいい。いじったあとはservice sshd restart。たとえばOSを入れ直して再度設定しているときなどはローカル側の.ssh/knwon_hostsに既に設定されている場合があるので消しておく。 いちいちPasswordAuthenticationをいじらねばならんのめんどくさいのでむしろvim ~.ssh/authorized_keysして公開鍵をコピペできる環境ならそっちのほうが楽そう
  6. ssh接続できたら/etc/ssh/sshd_configのセキュリティたらへんをアレしておく。ポート番号が22でないか、rootには入れないか、パスワード認証で入れないか、など
  7. クライアントの~/.ssh/configをいじってsshやるときいろいろ省略できるようにしておく

くらいです。このあとmysqlとnginxをいれてVirtualHostやる予定。