unzip file which contains symbolic link by zip-rs

zip-rs does not support symbolic link yet(https://github.com/zip-rs/zip/issues/77). However it is possible by using public APIs as below.

use std::fs;
use std::io;

fn main() {
    std::process::exit(real_main());
}

fn real_main() -> i32 {
    let args: Vec<_> = std::env::args().collect();
    if args.len() < 2 {
        println!("Usage: {} <filename>", args[0]);
        return 1;
    }
    let fname = std::path::Path::new(&*args[1]);
    let file = fs::File::open(&fname).unwrap();

    let mut archive = zip::ZipArchive::new(file).unwrap();

    for i in 0..archive.len() {
        let mut file = archive.by_index(i).unwrap();
        let outpath = match file.enclosed_name() {
            Some(path) => path.to_owned(),
            None => continue,
        };

        {
            let comment = file.comment();
            if !comment.is_empty() {
                println!("File {} comment: {}", i, comment);
            }
        }

        if (&*file.name()).ends_with('/') {
            println!("File {} extracted to \"{}\"", i, outpath.display());
            fs::create_dir_all(&outpath).unwrap();
        } else {
            println!(
                "File {} extracted to \"{}\" ({} bytes)",
                i,
                outpath.display(),
                file.size()
            );
            if let Some(p) = outpath.parent() {
                if !p.exists() {
                    fs::create_dir_all(&p).unwrap();
                }
            }

            let is_symlink = if cfg!(unix) {
                const S_IFLINK: u32 = 0o120000;
                file.unix_mode().unwrap() & S_IFLINK == S_IFLINK
            } else {
                false
            };

            if is_symlink {
                #[cfg(unix)]
                {
                    use std::io::Read;
                    use std::os::unix::fs;

                    let mut data = Vec::new();
                    file.read_to_end(&mut data).unwrap();
                    let original = String::from_utf8(data).unwrap();
                    fs::symlink(original, outpath).unwrap();
                }
            } else {
                let mut outfile = fs::File::create(&outpath).unwrap();
                io::copy(&mut file, &mut outfile).unwrap();
                // Get and Set permissions
                #[cfg(unix)]
                {
                    use std::os::unix::fs::PermissionsExt;

                    if let Some(mode) = file.unix_mode() {
                        fs::set_permissions(&outpath, fs::Permissions::from_mode(mode)).unwrap();
                    }
                }
            }
        }
    }

    return 0;
}

Advent Of Code 2020を終えて

memo.sugyan.com

yosuke-furukawa.hatenablog.com

今年始めて参加した Advent of Code 2020年版を終えました

f:id:syohex:20201228212254p:plain

結果は上記のような感じ. 各問題 100位以内に解ければポイントがもらえるのですが, 100位なんて程遠すぎて結果は 0点. これは早くできたなと感じてもそんな問題はみんな早く解けているわけで自分が早く解けたときの方がむしろ順位は低かった印象. ポイントを取るにはまだまだ実力不足であることを感じました

Advent of Codeの特徴

  • コードの提出はない, 答えだけ提出
    • どんなに非効率なアルゴリズムでも答えが出ればいい. 微妙な問題サイズの場合はしばらく待てば解けてしまうこともあった
    • 超早いマシンを持っていれば幾分有利かも
  • 問題の入力が人によって違う
  • 世界中の人が多く解いているので解説が多数ある

感想

  • 初期の方は 1時間もかからず解けていたのであまり手応えがないって思っていたけど, 中盤からどんどん難しくなり休みをほとんど潰した日もあった
  • 問題が(無駄に)ストーリーがあり読んで理解するのに時間がかかる
    • 英語力が低いのが原因
    • 最速の人の解答時間に私の問題理解速度が追いついていないレベル. 10分ぐらい読んでやっとわかってことが多々あった
  • 入力のパースが面倒くさい
    • 去年はそんなことなかったらしいけど..
    • 構造と呼べるものも微妙だし, 問題によっては末尾に改行があったりなかったりと面倒くさかった
    • C++でずっと解いていたけど, 面倒くさくて Pythonで一問やってしまった. しかしC++で突き通そうということで全部 C++でやりましたが, 面倒くさかった
  • 例があるのは助かる
    • 例を見て問題をちゃんと理解できたということが多々あった
    • テストケースとして使える
    • しかし例があることで逆によくわからなくなることもあった(day 17の三次元, 四次元ライフゲーム)

問題の振り返り

全く解答が思いつかなかったという問題はありませんでしたが, 現実時間で解答を求められない問題がいくつかありそれらは解説を見た上で解答を作成しました. わからなかったのは以下の問題.

  • day 10 part2
    • 電源アダプタの並べ方が何通りあるかという問題. 愚直に求める方法しか思いつかず.
  • day 23 part2
    • ボール並び替えゲームを 1000万回やった後の並び方を求める問題. 愚直に求める方法しか思いつかず
    • 問題的に時間がかかることは予見できていたのだけど, 見当はずれの効率化を探していていつまで経っても効率的な方法が思い浮かばなかった

私の解答がいまいちだった問題として * day 15 part02 * 非効率的な実装だったけど, 3分ぐらい動かしていたら答えが出たのでそれで提出. 考え直したい

このあたりは単純に力不足だなと感じた. 来年はできれば解説を一つも見ずに完走したい. あとやっぱり自分で考えに考えて解くってのはやっぱり快感が伴うのでそういう意味でも自分で解けたらと思いました

最後に

楽しい経験ができたのと, まだまだ自分が力不足だということが認識できました. 来年も参加して 1ポイントでも取れるように実力をつけていければと思います

この半年でやったこと, 継続していること

studio3104.hatenablog.com

を見て, leetcodeがキリがいいところだったので, 私も真似して書いてみる. そもそも私は 40年近く生きてきて何かを継続してできたということがほとんどない. あったとしても若かりし頃のゲーセン通いぐらいで勉強に関してはおそらく皆無である. 今年の何ヶ月か過ぎたあたりでふと自分のキャリアについて考えたとき, 何もできることなくてこのままでいいのかとなって, (遅すぎるけど)いい加減真面目に考えないとまずいとなった. そこで雑ではあるが自分の幅を広げるために根本的なプログラミングスキルと英語をなんとかしようと思い, いろいろ試している. 初めて危機感を持った影響なのか今のところは毎日少しずつではあるが継続できていることもある. それらについてまとめておこうと思う.

leetcode

leetcode.com

@sugyanさんが Twitterで継続しているというのを見て自分もやってみようと思って始めた.

f:id:syohex:20201216221800p:plain

現状は上記の通りで今日で 500問分解いた. 基本的には C++で解いている. 他の人に比べると easyが圧倒的に多いので質的にどうなのかというのがあるが.. アルゴリズム系はまるっきりダメだったのでとりあえず easyからひたすらやっていった. 初期の頃は mediumでもものすごい難しく感じてこれで mediumなのかと自分のレベルの低さに驚いた.

現状

  • mediumぐらいならなんとかなるかなってことは増えた. ただ mediumでもまだまだすんなりとはいかない問題は多い.
  • アルゴリズムを考えるときは計算量をなるべく意識できるようにはなった.
  • 苦手な分野(=勉強しなくてはいけない分野)が何なのか見えてきた.

取り組み方

  • できれば一日 1問は解く. dailyの課題は見て, なんとかなりそうなら解く. 全く無理そうなら諦める
  • 同じ問題を何度も解く
    • 1月前とかにやった問題を改めて解こうとするとすんなり解けないことが案外多かったりするので, しっかり理解していることを確認するために過去に解いた問題でも定期的にやっている.
    • それで過去の結果と比べてより早かったり, コードがスマートに書けていると成長を感じる. 同じところでハマったりすると改めてちゃんと確認する

leetcodeのいいところ

  • 問題がテストを書きやすい
    • 基本的には関数の引数と戻り値で考えられるのでテストしやすい. AtCoderだと入力・出力が標準入出力だからそもそも面倒くさい.
  • 世界中でやっている人がいるので参考にできるものが多い. コードしかり解説然り

leetcodeのあまり良くないと感じたところ

  • 問題のレベル判定が雑. easy, medium, hardが当てにならないこともある
  • 条件が雑, 問題分が不親切なものが少なからずある
  • SQLの問題がクイズみたいなのばっかりで実際の現場で書く SQLではないことがほとんど

iknow

iknow.jp

初めは英会話スクールを考えていたのだけど, コロナだし, そもそも私 TOEIC 300点ぐらいの論外レベルなのでまずは基礎だろうということで英単語から始めるということで iknowを始めてみました.

f:id:syohex:20201216223444p:plain

現状は上記のような感じで毎日 40-50分程度 200日ぐらい継続できている.

現状

  • 単語力は少し上がったような気はするが, まだまだわからない単語が多い.
  • 元が低すぎてあれだけど, 英語力が伸びたという感じはまだまだしないがすぐ伸びるものでもないので継続したいとは考える.

取り組み方

  • ひたすら単語 + 文章問題をやる

LingoChamp

www.lingochamp.com

先月ぐらいから始めており, 現在 45日間ぐらい継続している. iknowだけだと知識だけだし話す練習もした方がいいかと思って始めた. LingoChampでは何か喋ったあと自分の声を流されるのですが, 本当に自分の発音がダメダメなと気付かされる. 某米国在住の日本人の方のプレゼンなどを見たときに英語の発音がネイティブっぽくないなぁとか生意気にも思っていたことがあったけど, 自分の発音はもっと論外ということに気付かされた.

現状

  • 自分の発音のひどさを実感した
  • 単純な単語でも全然正しく発音できないものが多々あることに気付かされる
  • 大学のときなど発音がひどいとよく怒られていてそのとき何も理解できなかったけど, ここが変だったのかというのに 20年ぐらいして気付かされた.
  • 発音するとき意識をするようになった(本当は無意識で適切な発音がいいのだろうけど, その域にはまだまだ到達できない)

取り組み方

  • 毎日 20-30分課題をやる

その他

AtCoder

atcoder.jp

  • たまに解いている. A, Bと Cをたまにって感じ. leetcodeよりも難しい印象. leetcodeと違い, 数値の範囲を意識しないといけないことが多い.
  • 前述の通り標準入出力を使うのは若干手間だと感じている.

ELLLO

elllo.org

  • 学習サイトって感じではあまりないけど, リスニングのためにたまに聞いている
  • 日常会話と言われるとやや違う気もするけど, ありそうな会話ではあるので面白い. いざしゃべるとなるとこんな感じでスラスラ言えないといけないんだろうなぁと感じる

Advent of Code

adventofcode.com

  • これも sugyanさん経由で知って始めてみた.
  • 今のところ 1問だけ常識的な時間で解く方法がわからなくて解説を見た以外は自力で解けている. できれば完走したい.

最後に

ここまで自分が何かを継続できていることが信じられないが, 現状なんとかやれている. ただ正直なところ継続できている一番大きな理由はこの一年仕事が全くうまくいっておらず何の成果も上げられていない反動によるところが大きいと思う. 今後仕事がどうなるかはわからないけどこれらのことを継続していって自分の能力を上げることにつなげていればと思う.

年取ったからって遅いってことはないと思いますが, 若い内からやるに越したことないので若い人はなるべく早くやるといいと思います.

vscodevimで Ctrl- keyは VScodeのものを使うようにする

IdeaVimとか VSVim(Visual Studio)は IDEのキーを優先するのをデフォルトにできるのだけど, vscodevimはデフォルトだとめちゃ VimVScode本来のショートカットキーがほとんど使えない. macOSだと Command keyベースで Ctrlキーのものと衝突しないというのはあるが, Windows, Linuxではコンフリクトする. Vim好きならそれでいいんだろうけど, 個人的には Ctrl-wの画面分割ぐらいしか使わないので, VScode本来のキーを使う方法をようやく調べてみた.

結論としては vim.handleKeys を調整すればよかった. File -> Preferences -> Settingsから handlekeysで検索するとヒットするので以下のように設定した.

    "vim.handleKeys": {
        "<C-a>": false,
        "<C-f>": false,
        "<C-n>": false,
        "<C-c>": false,
        "<C-x>": false,
        "<C-v>": false,
        "<C-b>": false,
        "<C-j>": false,
        "<C-k>": false
    }

しばらくこれで試してみる.

C#で簡素な Scheme処理系を書いてみた

github.com

peter.michaux.ca

C#でやった. C#で書いたのは最近 Unityにふれることがあるのでその影響. C#らしい部分はほとんどない. むしろ書きづらかったさえある. あとこの前に Common Lisp風の処理系を書いていたのでシンボルと値の扱いに 若干混乱した. 処理も無駄に複雑になってしまったと思う. あと C#力が低すぎるというのもあり, クオリティは低い. まだまだ勉強する必要がある.

Linux環境で JetBrains Riderで書いたけど, Visual Studioの出来がいいから(特に C#開発ではすごい), 競合する C#IDEの出来はいいんだなと感心した(言語の性質的なところもあるんだろうけど, CLionもそれぐらい便利だったらなぁと思った)

Goで簡素な Lisp処理系を書いた

github.com

最近 Goに触れていなかったので復習も兼ねて. 内容としては下記の本に載っている Common Lisp風の簡易 Lisp. 本では Common Lispで書いているので read周りとか楽にできる部分があるのだけれど, Lisp系言語以外だとそんなわけにはいかないのでそこは地道に書いた. あとオブジェクト指向というかクラス継承を使って書かれていた部分を Goっぽく(?)落とし込んで書いた. その他の方針などはだいたい本のまま. 以前もっと簡単なものを Cで書いたことはあったけど, それよりは幾分進んだ内容で適度にいい刺激にはなったかと思いました.

対話によるCommon Lisp入門

対話によるCommon Lisp入門

最近読んだ漫画

アニメがすごく面白かったので購入. アニメいいけど, 漫画も良かった. アニメでは省かれているけど, 原作では準備の前の説明とか調理前の説明などが充実しており全く知らない自分にとってもわかりやすかった. 締めるシーンも原作以上にあり, 生き物を食べるということがどういうことかというのもちゃんと描画しているのがよいです. 釣りには一ミリも興味がないけど, とても楽しめた. 作者の方が熊本豪雨で被災して一時休載というのが残念. 再開の見通しはたっているそうなので, 話がまた貯まったら 2期に期待したい

amazonの recommendに出てきてそういえばアニメ見ていたなということで購入. なかなか楽しめた. 今アニメが放送されたら主人公の名前と父親の声優から, 絶対にゴーストオブツシマネタで盛り上がったんだろうなと思った. こちらも 2期があれば是非みたい.