見出し画像

Retro-gaming and so on

RE: プログラミング「学習」日記 2022/05/10〜

星田さんの記事に対するコメント。

 2進数への変換コード。打ちはじめてびっくり、全然指が動かねぇ・・以前はPythonで学習をしてたのに全く分からなくなってるw 

うん、無事Lispに脳が侵されてるね(笑)。
最初はPython <-> Lispの行き来に若干混乱するかもしんない。
でも慣れます(笑)。
っつーかね、だから「Pythonのコードらしいコード」じゃなくって「C言語脳が書いたPythonコード」に拒否感が生じるでしょう。
それは「正しい感覚」なんです。
自分を信頼しよう。
多分その本のコードがあんまり「美しくない」んだ。

 今度は16進数変換コード。こういうアルゴリズムだったのか・・・これが分かってればX68000ももうちょっと楽しめた(かも知れない)のになぁ。

ちなみに、僕だったらそんな風には書かない。
そもそも、10 => 'A' なんつー変換をif ~ else で書くのはメンドイでしょ?
そういうときはハッシュテーブル使って「変換テーブル」を書いちゃうのが吉です。
そうすればコードが圧縮されて短くなります。

def dec2hex(target):
 acc = []
 # ここで変換テーブルを作っちゃう
 table = {10 : 'A', 11 : 'B', 12 : 'C', 13: 'D', 14 : 'E', 15 : 'F'}
 while target != 0:
  acc += [target % 16]
  target //= 16
 # for でダラダラ書くならリスト内包表記を
 # Lispなら map を使う局面だ!
 return list(reversed([table[i] if i > 9 else i for i in acc]))

せっかくなので16進数変換コードをRacketに移植してみる。上のLetはいらんかったな・・。とりあえずこれで動くので、ここから10〜15までの場合はABCDEFに変わるようにするには・・

いや、よく書けてますよ(オプショナル引数の導入、とか上手い)。
ちなみに、僕ならこう書く。っつーか発想はPython版と同じ。

(define (hex target)
 (let ((table '((10 . A) (11 . B) (12 . C)
          (13 . D) (14 . E) (15 . F))))
  (let loop ((target target) (acc '()))
   (if (zero? target)
    (map (lambda (x)
       (if (> x 9)
        (cdr (assv x table))
        x)) acc)
    (loop (quotient target 16)
       (cons (modulo target 16) acc))))))

直接末尾再帰せずに名前付きletを使った理由は、変換テーブルも再作成されるのを避ける為。再帰部分は再帰部分で独立しておけば、変換テーブル作成は巻き込まれない。

今話題のX68000にあやかって68000を変換してみる。これあってんのかなw。

合ってます。
Racketで16進数が正解かどうか調べるには、

> #x109A0
68000
>

と直接16進数を入力してみれば良い。

  • #x -> 16進数接頭辞
  • #o -> 8進数接頭辞
  • #b -> 2進数接頭辞
で全部で3種類、すぐさま10進数に直して返してくれます。
あるいは、本当はRacketなら

(define (hex target)
 (number->string target 16))

って書いても良くって、組み込み関数number->stringは数値を文字列に直すんだけど、その際に基数を指定できるのね。上の例だと16を与えて16進数表記なんだけど、例えば2を与えると2進数表記の文字列に変換してくれる。
従って、

> (string->number "109a0" 16)
68000
>

と元に戻れば計算が成功してる、と言うことになる。

ちなみにPythonでは

0x109a0

と書いて、

  • 16進数は0xではじまる
  • 8進数は0oではじまる
  • 2進数は0bではじまる
とすれば全部10進数に変換して「答え合わせ」が可能です。

参考まで、に。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「RE: プログラミング「学習」日記」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事