Brainfu*kからのSquidFubkを作った。(common lisp)

github.com

brainfuckインタプリタを作っていましたが、
面白いことをするために
イカが陣取りをするゲームの効果音を取り込んでみました。

ジョーインタプリタです。

ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!
ウシロォォォ!ヤリッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ヤリッ!
ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ヤリッ!ドッ!ドッ!ドッ!ドッ!ドッ!アブネッ!
アブネッ!アブネッ!ビチャッ!ソコハヒケヨッ!ヤリッ!ヤラレタッ!ヤリッ!ドッ!ドッ!ヤラレタッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ヤラレタッ!
ヤラレタッ!ドッ!ドッ!ドッ!ヤラレタッ!ヤリッ!ビチャッ!ヤラレタッ!
ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!
ヤラレタッ!アブネッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!ドッ!
ヤラレタッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!
ビチャッ!ヤラレタッ!ドッ!ドッ!ドッ!ヤラレタッ!ビチャッ!ビチャッ!ビチャッ!
ビチャッ!ビチャッ!ビチャッ!ヤラレタッ!ビチャッ!ビチャッ!ビチャッ!ビチャッ!
ビチャッ!ビチャッ!ビチャッ!ビチャッ!ヤラレタッ!ヤリッ!ドッ!ヤラレタッ!

上記hello worldです。

結局Common lispで書きました。
遊んでみてください:)

BrainF*ckのインタプリタ書いてみた(C言語)

自分的にはすごい綺麗な書き方ができたと思っているのですがどうでしょうか?(自画自賛
何か感想などがあれば教えてください。

#include<stdio.h>
#include<stdlib.h>

int main() {
      unsigned char *p = malloc(10000);

      //100までの素数を表示する
      char *str = "\
                   >++++[<++++++++>-]>++++++++[<++++++>-]<++.<.> +.<.> ++.<.> ++.<.> ------..<.>\
                   .++.<.> --.++++++.<.> ------.>+++[<+++>-]<-.<.> -------.+.<.> -.+++++++.<.>\
                   ------.--.<.> ++.++++.<.> ---.---.<.> +++.-.<.> +.+++.<.> --.--.<.> ++.++++.<.>\
                   ---.-----.<.> +++++.+.<.> .------.<.> ++++++.----.<.> ++++.++.<.> -.-----.<.> +++++.+.<.> .--.\
                   ";
      char *save;

      for(;*str != '\0';str++){
            switch(*str){
                  case '>': // ポインタをインクリメント
                        p++;
                        break;
                  case '<': // ポインタをデクリメント
                        p--;
                        break;
                  case '+': { // ポインタが指す値をインクリメント
                                  int a = (int)*p;
                                  a++;
                                  *p = (char)a;
                            }
                            break;
                  case '-': { // ポインタが指す値をデクリメント
                                  int a = (int)*p;
                                  a--;
                                  *p = (char)a;
                            }
                            break;
                  case '.': // ポインタが指す値を出力する
                            putchar(*p);
                            break;
                  case ',': // ポインタが指す値に代入する
                            *p = getchar();
                            break;
                  case '[': //ポインタが指す値が0なら対応する]の直後までジャンプする
                            if(*p == 0){
                                  while(*str == ']'){
                                        str++;
                                  }
                            }else{
                                  save = str;
                            }
                            break;
                  case ']': // ポインタが指す値が0でないなら対応する[にジャンプする
                            if(*p != 0) {
                                  str = save;
                            }
                            break;
                  default: // それ以外コメントアウト
                            break;
            }
      }

}

これを何か面白そうな構文を作って
外部ファイルを読み込む処理を書けば楽しめそうですね。
今日は綺麗に書けたことをできるだけ早く公開したかったです(自画自賛

NANDゲートから加算器作ってみた(common lisp)

NANDゲートから加算器作ってみました。
これでマインクラフトで計算機が作れるようになるのでは無いか??

(defmacro let1 ((k v) &body body)
  `(let ((,k ,v))
     ,@body))

(defun end (lst)
  (first (rest lst)))

;; nand gate
(defun nand-g (in1 in2)
  (if (>= (+ in1 in2) 2) 0 1))

;; not gate
(defun not-g (in)
  (nand-g in in))

;; and gate
(defun and-g (in1 in2)
  (nand-g (nand-g in1 in2) (nand-g in1 in2)))

;; or gate
(defun or-g (in1 in2)
  (nand-g (nand-g in1 in1) (nand-g in2 in2)))

;; nor gate
(defun nor-g (in1 in2)
  (not-g (or-g in1 in2)))

;; xor gate
(defun xor-g (in1 in2)
  (or-g (and-g (not-g in1) in2) (and-g in1 (not-g in2))))

;; マルチプレクサ
(defun mux (in1 in2 sel)
  (or-g (and-g in2 (not-g sel)) (and-g in1 sel)))

;; デマルチプレクサ
(defun dmux (in sel)
  (if (= sel 1)
    (list 0 in)
    (list in 0)))

;; 16bit用のゲート
(defun in1-gate16 (gate in1)
  (let1 (lst '())
        (dotimes (i 16)
          (push (funcall gate (nth i in1)) lst))
        (reverse lst)))

;; 16bit用入力二つ用のゲート
(defun in2-gate16 (gate in1 in2)
  (let1 (lst nil)
        (dotimes (i 16)
          (push (funcall gate (nth i in1) (nth i in2)) lst))
        (reverse lst)))

;; 半加算器
(defun ha (in1 in2)
  (let ((s (and-g in1 in2))
        (c (xor-g in1 in2)))
    (list s c)))

;; 全加算器
(defun fa (in1 in2 up)
  (let* ((lst1 (ha in1 in2))
         (lst2 (ha (end lst1) up))
         (c (or-g (first lst1) (first lst2))))
    (list c (end lst2))))

;; 加算
(defun sum (in1 in2)
  (let ((carry 0)
        (rst '())
        (in1 (reverse in1))
        (in2 (reverse in2)))
        (dotimes (i 16)
          (let1 (fa-lst (fa (nth i in1) (nth i in2) carry))
                (push (end fa-lst) rst)
                (setf carry (first fa-lst))))
        rst))

;; 2の補数
(defun 2comp (in)
  (dotimes (i 16)
    (setf (nth i in) (not-g (nth i in))))
  (sum in '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1)))

(defvar *lst1* '(0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1)) ; 2017
(defvar *lst2* '(0 0 0 1 0 1 0 0 1 0 1 1 0 1 0 0)) ; 5300

; 2017 + 5300
(print (sum *lst1* *lst2*)) ;-> (0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1) = 7317

; 2017 - 5300
(print (sum *lst1* (2comp *lst2*))) ; -> (1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 1)  = -3283

lisp楽しいですね。
ちょっとしたスクリプトlispで書けるようになりたいな。
なんだかんだまだpythonとか書いちゃいますね。。。

common lisp マクロ入門

lispを少しずつ勉強しています。
マクロを書いてみました。

(defmacro list3 (a b c)
  `'(a b c))

(defmacro let1 ((var val) &body body)
  `(let ((,var ,val))
     ,@body
     ))

(defmacro -unless (bool &body body)
  `(if (not ,bool)
     (progn
       ,@body)
     nil))

(print (macroexpand-1 '(list3 :a :b :c)))
(print (macroexpand-1 '(let1 (c 2) (print c))))
(print (macroexpand-1 '(-unless (= 1 1) (print "HI"))))

フロントエンドというかhtml, cssが嫌いなので
lispのマクロで苦にならないようなものを作りたいです。

なんかちょっと楽しいぞ( ̄ー ̄)

common lisp の first car

最近common lispをより深く知りたくて
趣味で作っているアプリのサーバー部分をcommon lispで書こうとしています。

通勤時間に「実践Common lisp」を読んでいるのですが、
car, cdrは古いみたいですね。
これからはfirst, restを使っていきたいと思います。

サーバーはcaveman2を使ってみたいと思います。
フロントはunityです。

時間があれば、そっち側もブログに書けたらいいなと思っています。
もうすでにcaveman2動かすまでかなりの時間を使ってます笑

rubyでgem公開してみた。

rubyで初めてgemを公開してみました。

github.com


rubytrisというテトリスのgemです。
オープンソースの開発とかも携わっていけたらいいな.

phpで使いそうな画像処理のクラス2

前回のコードが時間がないままフレームワークの中で使っていたものを汎用的にしたので
最悪だったのですが
今回はまだマシかと思います。
とりあえず直しただけ多分動く

一つ目は戒めとして残しておきます。

<?php
class ImageChanger{
      const FILE_MAX_LENGTH = 750;
      const COMPRESSION = 60;

      private $target_file;
      private $width;
      private $height;
      private $type;

      function __construct($target){
            $this->target_file = $target;
      }

      /* public method */
      public function getFile(){ return $this->target_file; }

      //画像の縮小
      public function createImage(){ //->bool
            if(file_exists($this->target_file) == false){
                  return false;
            }
            $this->getImageInformation();
            $size = $this->imageSize(self::FILE_MAX_LENGTH);
            //型作り
            $new_image = imagecreatetruecolor($size['width'], $size['height']);

            switch($this->type){
            case 'image/gif':
                  $base_image = imagecreatefromgif($this->target_file);
                  break;
            case 'image/png':
                  $base_image = imagecreatefrompng($this->target_file);
                  break;
            case 'image/jpeg':
            case 'image/jpg':
                  $base_image = imagecreatefromjpeg($this->target_file);
                  break;
            default:
                  return false;

            }
            //型に合わせて作成
            imagecopyresampled($new_image, $base_image, 0, 0, 0, 0, $size['width'], $size['height'],  $this->width, $this->height);
            ImageDestroy($base_image);

            //元データの削除
            if(file_exists($this->target_file)){
                  unlink($this->target_file);
                  $this->target_file = "";
            }
            $file_path = $this->getNewImagePath();

            imagejpeg($new_image, $file_path, self::COMPRESSION);
            ImageDestroy($new_image);

            $this->target_file = $file_path;
            return true;
      }

      //画像の向きを元に戻す
      public function rotateImage(){ //->bool
            if(file_exists($this->target_file) == false){
                  return false;
            }
            $this->getImageInformation();

            if($this->type != "image/jpeg" && $this->type != "image/jpg"){
                  return true;
            }
            //型作り
            $new_image = imagecreatetruecolor($this->width, $this->height);

            $exif = $this->exifInformation($this->target_file);
            if($exif == null){
                  return false;
            }

            $base_image = imagecreatefromjpeg($this->target_file);
            if(isset($exif['IFD0']['Orientation'])){
                  //回転処理
                  $rotate_infos = $this->imageRotation($exif['IFD0']['Orientation']);

                  //反転
                  if(!empty($rotate_infos['mode'])){
                        $base_image = imageflip($base_image, $rotate_infos['mode']);
                  }

                  //回転
                  if($rotate_infos['degrees'] > 0){
                        $base_image = imagerotate($base_image, $rotate_infos['degrees'], 0);
                  }
            }

            //元データの削除
            if(file_exists($this->target_file)){
                  unlink($this->target_file);
                  $this->target_file = "";
            }
            $file_path = $this->getNewImagePath();

            imagejpeg($base_image, $file_path, self::COMPRESSION);
            ImageDestroy($base_image);

            $this->target_file = $file_path;
            return true;
      }


      /* private method */
      //同じ縦横比のまま長いほうが指定した数値になるように縦横を返す
      private function imageSize($max_length){ // -> [int, int]
            if($this->width < $max_length || $this->height < $max_length){
                  $w = $this->width;
                  $h = $this->height;
            }elseif($this->width > $this->height){
                  $ratio = $this->height / $this->width;
                  $w = $max_length;
                  $h = round($w * $ratio);
            }elseif($this->width < $this->height){
                  $ratio = $this->width / $this->height;
                  $h = $max_length;
                  $w = round($h * $ratio);
            }else{
                  $w = $max_length;
                  $h = $max_length;
            }
            $size = ['width' => $w, 'height' => $h];
            return $size;
      }

      private function getNewImagePath(){ // -> string
            $name = str_replace('.', '', microtime(true));
            $filepath = 'tmp/'. $name. '.jpeg';
            return $filepath;
      }

      //file 情報取得
      private function getImageInformation(){ //->void
            $infos = getimagesize($this->target_file);
            $this->width = $infos[0];
            $this->height = $infos[1];
            $this->type = $infos['mime'];
      }


      //exif情報取得
      private function exifInformation(){
            if(file_exists($this->target_file) == false) return null;
            $exif = exif_read_data($this->target_file, 0, true);
            if($exif === false){
                  return null;
            }else{
                  return $exif;
            }
      }

      //イメージの回転修正
      //ファイルのパスをもらって回転の処理に必要な$mode, $degreesを返す
      private function imageRotation($exif){ //-> [string, int]
            if(isset($exif) == false){
                  return ["", 0];
            }
            $degrees = 0;
            $mode = '';

            switch($exif){
            case 1:
                  break;
            case 2:
                  $mode = 'IMG_FLIP_HORIZONTAL';
                  break;
            case 3:
                  $degrees = 180;
                  break;
            case 4:
                  $mode = 'IMG_FLIP_VERTICAL';
                  break;
            case 5:
                  $degrees = 90;
                  $mode = 'IMG_FLIP_HORIZONTAL';
                  break;
            case 6:
                  //$degrees = 90;
                  $degrees = 270;
                  break;
            case 7:
                  $degrees = 90;
                  $mode = 'IMG_FLIP_VERTICAL';
                  break;
            case 8:
                  $degrees = 270;
                  break;
            }

            return ['mode' => $mode, 'degrees' => $degrees];
      }

}