How to spend the terminal

技術ブログでさえない

初心者向けプログラミング言語 BASIC

この記事はSLP KBIT Advent Calendar 2014 - Adventarの9日目の記事です。



はじめに

初心者向けプログラミング言語としてBASICを紹介します。
古すぎ?現代の初心者に教えるべきでない?いやいや初心者向けであることには変わらない。

BASICとは

BASICとは

Beginner's
All-purpose
Symbolic
Instruction
Code

の略で、初心者向け汎用記号命令コードという意味です。
オリジナルはコンパイラですが、多く出回っているのはインタプリタです。
今年で生まれてから50年です。
センター試験数学IIの選択問題で出てきます。(コンピュータと計算)
僕は数列が苦手だったのでやりました。(結果は聞かないで)
BASICについて詳しく知りたい方は
http://ja.wikipedia.org/wiki/BASIC
を見て下さい。

僕とBASICの出会い

僕とBASICが初めて出会ったのは2013年、ハードオフポケコン「PC-G850VS」を購入した時です。
触って少ししてパソコンでC言語を勉強し始めました。
なのでそこまでBASICに慣れていないです。
f:id:moxtsuan:20141105211455j:plain

プログラムを見てみよう

BASICプログラムを見たことのない人が多いような気がするのでプログラムを書いてみます。
ちなみに実行する時は

RUN

を入力します。

代入とか

10 LET A=10
20 LET B=12.3
30 LET S$="HELLO"
35 REM 出力
40 PRINT A
50 PRINT B
60 PRINT S$
70 END

結果

10
12.3
HELLO

LETは代入します。
変数には数値型と文字列型があります。
変数名の最後に$がついているのは文字列型です。
数値型には整数と実数が入ります。
REMはコメント(行末)です。
PRINTは出力です。

PRINT "hello world"

というように文字列を出力できますし

PRINT A/B

というように計算結果も出力できます。
ENDはプログラムの終わりを表しています。

入力して出力するプログラム

10 INPUT A
20 PRINT A
30 END

INPUTは入力です。

INPUT PROMPT "文字列":A

とすると文字列を出力してから入力を求める...らしいです。
PC-G850VSではエラーになります。

条件による分岐

条件による分岐を行いたいときはIF文を使います。

IF 条件式1 THEN 命令1
ELSE IF 条件式2 THEN 命令2
ELSE 命令3

まず条件式1を評価して真(その通り)であれば命令1を行います。
偽(そうでない)であれば条件式2を評価して真であれば命令2を行い、
偽であれば命令3を行います。

C言語と違うのは条件式でA==10の場合A=10と書き、
A!=10の場合A<>10と書きます。


繰り返し

繰り返しの命令がしたい時はこのようにします。

10 FOR I=0 TO 5
20 PRINT I
30 NEXT
40 END

結果

0
1
2
3
4
5

FORは繰り返すことができます。

FOR I=A TO B STEP C
NEXT

まずIにAを代入し、NEXTまで進むとCだけ足して(何も書かないと1だけ)
Bになるまで繰り返します。
処理系によってはWHILE~WENDもあります。
使い方は割愛します。

配列

配列は

10 DIM A(5)

というふうに宣言できます。
C言語風に書くと

int A[5]

です。
使い方は割愛します。

GOTO is God

GOTOは指定された行番号にジャンプします。
アセンブラ言語のJMPのようなものです。

10 PRINT "GOTO is God"
20 GOTO 10
30 END

このコードは永遠に"GOTO is God"を出力し続けます。


GOTO is God

ちなみにGOTO教はBASICなど一部の言語以外では迫害されるのでカミングアウトしないほうがいいです。

その他

その他いろんな命令があります。
C言語の関数のように扱えるGOSUB、出力する場所を変えるLOCATEなどがあります。

BASICを使うには

ここまで読んでBASICを使いたくなった物好きな方は以下のものをおすすめします。
・99 BASIC(Windows)
使いやすい(らしい)BASIC。
・(仮称)十進BASIC(WindowsLinuxMac OS)
センター試験に近い(らしい)BASIC。
・Chipmunk Basic(Mac OSWindowsLinux)
元々はMac OS用に開発されたフリーウェア。
オブジェクト指向プログラミングが可能。
プチコン(ニンテンドーDSiニンテンドー3DS)
ゲーム機で出来るBASIC。

VisualBasicとSmallBasicとActiceBasicはもはや別物だと思う...

おすすめサイト

BASICを学びたいなら以下のサイトがおすすめです。
・ドットインストール BASIC入門
http://dotinstall.com/lessons/basic_basic
なぜある!


最後に

工業高校ではBASIC、商業高校ではCOBOL(今年で55年)というように50年ものの古代言語はひっそりと生きてきました(LISP?いやいやそんな最新鋭を行く言語は)。
しかしBASICを学ぶ環境であるPC-G850VSは昨年度で生産完了しました。
もう若い人は学ばないのかもしれません(プチコンあるから学ぶ人もいると思うけど)。
僕はBASICという言語を知っているので布教しなければいけません。
こんな言語学ばないほうがいいと思うよ!
スパゲティコード書いちゃうようになっちゃうし。
というわけでBASICのお話でした。

3つの値の最大値を求めるプログラム10言語分

この記事はSLP KBIT Advent Calendar 2014 - Adventarの2日目の記事です。

はじめに

やあ (´・ω・`)
ようこそ、当ブログへ。
この記事は時間稼ぎだから、まず読んで落ち着いて欲しい。
うん、「処分市」なんだ。済まない。
仏の顔もって言うしね、謝って許してもらおうとも思っていない。
でも、このタイトルを見たとき、君は、きっと言葉では言い表せない
「ときめき」みたいなものを感じてくれたと思う。
殺伐とした世の中で、そういう気持ちを忘れないで欲しい、そう思って
この記事を作ったんだ。
じゃあ、注文を聞こうか

本題

入力された3つの値の最大値を求めるプログラムを10言語分書いてみた。
使用言語はC、C++JavaRubyPythonJavaScript、なでしこ、FORTRANBASICシェルスクリプトである。

C言語

#include <stdio.h>

int main(void)
{
  int num1,num2,num3;
  int max;
  
  scanf("%d",&num1);
  scanf("%d",&num2);
  scanf("%d",&num3);
  
  max = num1;
  if( max < num2 ) {
    max = num2;
  }
  if( max < num3 ) {
    max = num3;
  }
  
  printf("%d\n",max);
  
  return 0;
}

C++

#include <iostream>

using namespace std;

int main(void)
{
  int max;
  int num1,num2,num3;
  
  cin >> num1;
  cin >> num2;
  cin >> num3;
  
  max = num1;
  if( max < num2 ) {
    max = num2;
  }
  if( max < num3 ) {
    max = num3;
  }
  
  cout << max;
  
  return 0;
}

C++(C++11)

#include <iostream>
#include <algorithm>

using namespace std;

int main(void)
{
  int num1,num2,num3;
  
  cin >> num1;
  cin >> num2;
  cin >> num3;
  
  cout << max( {num1, num2, num3} );
  
  return 0;
}

Java

import java.util.Scanner;

public class Max {
  public static void main(String[] args) {
    int num1,num2,num3;
    int max;
    int i;
    
    Scanner input = new Scanner(System.in);
    
    num1 = input.nextInt();
    max = num1;
    num2 = input.nextInt();
    if( max < num2 ) {
      max = num2;
    }
    num3 = input.nextInt();
    if( max < num3 ) {
      max = num3;
    }
    
    System.out.printf("%d\n",max);
    
  }
  
}

Ruby

# coding: utf-8

num = [gets.to_i, gets.to_i, gets.to_i]
puts num.max 

Python

# -*- coding: utf-8 -*-

num = [input(), input(), input()]
max(num)

JavaScript

num1 = window.prompt("数1");
num2 = window.prompt("数2");
num3 = window.prompt("数3");
 
max = num1;
if( max < num2 ) {
  max = num2;
}
if( max < num3 ) {
  max = num3;
}

document.write("最大値は" + max );

なでしこ

最大とは整数。
数1とは整数。
数2とは整数。
数3とは整数。

「数1:」と尋ねる。
数1はそれ。
「数2:」と尋ねる。
数2はそれ。
「数3:」と尋ねる。
数3はそれ。

最大に数1を代入。
もし、最大 < 数2ならば
	最大に数2を代入。
もし、最大 < 数3ならば
	最大に数3を代入。

最大を表示。

BASIC

10 INPUT NUM1
20 INPUT NUM2
30 INPUT NUM3
40 MAX = NUM1
50 IF MAX < NUM2 THEN MAX = NUM2
60 IF MAX < NUM3 THEN MAX = NUM3
70 PRINT MAX
80 END

FORTRAN

program max
  integer mx
  integer num1,num2,num3
  
  read *,num1
  read *,num2
  read *,num3
  
  mx = num1
  if( mx < num2 ) then
    mx = num2
  endif
  if( mx < num3 ) then
    mx = num3
  endif
  
  print *,mx
end program max

シェルスクリプト

#!/bin/sh

max=${1}
if [ ${max} -lt ${2} ]
then
   max=${2}
fi
if [ ${max} -lt ${3} ]
then
   max=${3}
fi

echo ${max}

まとめ

RubyPythonはマジックコメントを除けば2行で書ける(好ましくない書き方だと思われるが)ので、とても柔軟な言語だと思った。
正直こんな簡単なプログラムだとあまり違いがわからないので他のプログラムでもやってみたい。

B1の方々へ

togetterでもNAVERでも動画でもいいと思うので参加してみては?


12/2 C++(C++11)追記

順列と組み合わせの総数を求めるCプログラム

課題で順列と組み合わせの総数を求める問題が出されて、52P10とか非常にめんどいので作ってみた。

//------------------
// ヘッダファイル
//------------------
#include <stdio.h>

//------------------
// マクロ
//------------------

//------------------
// 主処理
//------------------

void PandC( int n, int r ) { // 順列と組み合わせを求める
  //--- 宣言
  int per;  // 順列
  int com;  // 組み合わせ
  int i;
  
  //--- 初期化
  per = 1;
  com = 1;
  
  //--- 計算
  for( i=0; i<r; i++ ) {
    per *= (n-i);
  }
  com = per;
  for( i=1; i<=r; i++ ) {
    com /= i;
  }
  //--- 出力
  printf("順列の総数は%d\n",per);
  printf("組み合わせの総数は%d\n",com);
  
  //--- 終了
  return;
}

int main(void)
{
  //--- 宣言
  int n,r;  // nPrとnCr
  //--- 入力
  while(1) {
    printf("nとrを入力して下さい(nPrとnCr)\n");
    printf("nに-1を入力すると終了です\n");
    scanf("%d %d",&n,&r);
    if( n >= 0 && r >= 0 && n >= r ) {
      PandC(n,r);
    } else if( n == -1 ) {
      break;
    } else {
      printf("正しい値を入力して下さい\n");
    }
  }
  //--- 終了
  return 0;
}

よろしければ使って下さい。
何かバグがあれば報告していただければ幸いです。

10.29 追記
52P10でやってみたところ変な値が出ましたが多分単純に値が大きすぎるからだと思います...

Vimにハイライトとスマートインデントを追加

正直Emacsを使いたかったのだがまだ時期尚早だろうというわけでVimを使うことにした(決してキーバインドに慣れるのが難しいというわけではない)。
Emacsの話はいつか使うということで置いといて、Vimを起動すると黒背景に真っ白の文字だけで、インデントを入れてくれるような親切なことはない。
これは「.vimrc」という設定ファイルを作れば解消されるようなので作ってみた。

set number // 行番号を表示
set tabstop=2 // タブ幅
set autoindent // オートインデント
set expandtab // タブをスペースに置き換える
set shiftwidth=2 // オートインデントでずれる幅
set softtabstop=2 // 連続した空白に対してタブキーでカーソルが動く幅
set smartindent // スマートインデント

syntax on // キーワード等の文字色を変える
set cursorline // カーソル行の背景色を変える

ネットで調べていろいろと追加した。
これでソースファイルが見やすくなった。

逆ポーランド記法による計算プログラムの負の整数対応版

昨日できそうと書いたので改造してみた。

//------------------------
// ヘッダファイル
//------------------------
#include <stdio.h>
#include <ctype.h>

//------------------------
// マクロ
//------------------------
#define STACK 10

//------------------------
// 主処理
//------------------------
int main(void)
{
  //--- 宣言
  int stack[STACK]; // スタック
  int stack_n;  // スタック位置
  int sum; // 合計
  int digit_f; // 数が連続した場合のフラグ
  int k;  // 一時変数
  int minus_f;  // -に数字が続くか
  char ch;  // 文字取り出し用
  //--- 初期化
  stack_n = 0;
  digit_f = 0;
  minus_f = 0;
  //--- 入力
  printf("計算式を入力して下さい(逆ポーランド記法)\n");
  while( (ch = getchar()) != '\n' ) { // 改行がくるまで入力を続ける
    //--- 計算
    if( isdigit(ch) ) { // 文字が整数('0'~'9')までの場合
      if( digit_f ) { // 整数が連続したかの判定
        stack[stack_n] = stack[stack_n] * 10 + (ch - '0');  // 連続した場合元の数に10かけてたす
      } else if( minus_f ){
        stack[stack_n] = -1 * (ch - '0');
        minus_f = 0;
      } else {
        stack[stack_n] = (ch - '0');
        digit_f++;
      }
    }
    if( isspace(ch) ) { // 空白なら
      if( digit_f ) { // 前の文字が整数だった場合
        stack_n++;
        digit_f = 0;
      }
      if( minus_f ) {
        //printf("-\n");  // デバッグ用
        if( stack_n > 1 ) {
          stack_n--;
        }
        stack[stack_n-1] -= stack[stack_n];
        stack[stack_n] = 0;
        minus_f = 0;
      }
    }
    if( ch == '+' ) { // 足し算
      //printf("+\n");  // デバッグ用
      if( stack_n > 1 ) {
        stack_n--;
      }
      stack[stack_n-1] += stack[stack_n];
      stack[stack_n] = 0;
    }
    if( ch == '-' ) { // 引き算
      minus_f++;
    }
    if( ch == '*' ) { // 掛け算
      //printf("*\n");  // デバッグ用
      if( stack_n > 1 ) {
        stack_n--;
      }
      stack[stack_n-1] *= stack[stack_n];
      stack[stack_n] = 0;
    }
    if( ch == '/' ) { // 割り算
      //printf("/\n");  // デバッグ用
      if( stack_n > 1 ) {
        stack_n--;
      }
      stack[stack_n-1] /= stack[stack_n];
      stack[stack_n] = 0;
    }
     /* for( k=0; k<=stack_n; k++ ) {  // デバッグ用
      printf("%d ",stack[k]);
    }
    printf("\n"); */
  }
  if( minus_f ) {
    //printf("-\n");  // デバッグ用
    if( stack_n > 1 ) {
        stack_n--;
      }
    stack[stack_n-1] -= stack[stack_n];
    stack[stack_n] = 0;
    minus_f = 0;
  }
  //--- 出力
  printf("%d\n",stack[0]);
  //--- 終了
  return 0;
}

改造する際に数が二つの場合うまく処理されないバグを見つけた。
最後の演算子が'-'の場合うまく処理されないので終わりに処理を書いた。

C言語による正の整数の四則演算が可能な逆ポーランド記法計算

なんとなく逆ポーランド記法を使ってみたのでC言語による逆ポーランド記法計算プログラムを作ってみた。

//------------------------
// ヘッダファイル
//------------------------
#include <stdio.h>
#include <ctype.h>

//------------------------
// マクロ
//------------------------
#define STACK 10

//------------------------
// 主処理
//------------------------
int main(void)
{
  //--- 宣言
  int stack[STACK]; // スタック
  int stack_n;  // スタック位置
  int sum; // 合計
  int digit_f; // 数が連続した場合のフラグ
  int k;  // 一時変数
  char ch;  // 文字取り出し用
  //--- 初期化
  stack_n = 0;
  digit_f = 0;
  //--- 入力
  printf("計算式を入力して下さい(逆ポーランド記法)\n");
  while( (ch = getchar()) != '\n' ) { // 改行がくるまで入力を続ける
    //--- 計算
    if( isdigit(ch) ) { // 文字が整数('0'~'9')までの場合
      if( digit_f ) { // 整数が連続したかの判定
        stack[stack_n] = stack[stack_n] * 10 + (ch - '0');  // 連続した場合元の数に10かけてたす
      } else {
        stack[stack_n] = (ch - '0');
        digit_f++;
      }
    }
    if( isspace(ch) ) { // 空白なら
      if( digit_f ) { // 前の文字が整数だった場合
        stack_n++;
        digit_f = 0;
      }
    }
    if( ch == '+' ) { // 足し算
      //printf("+\n");  // デバッグ用
      if( stack_n > 1 ) {
        stack_n--;
      }
      stack[stack_n-1] += stack[stack_n];
      stack[stack_n] = 0;
    }
    if( ch == '-' ) { // 引き算
      //printf("-\n");  // デバッグ用
      if( stack_n > 1 ) {
        stack_n--;
      }
      stack[stack_n-1] -= stack[stack_n];
      stack[stack_n] = 0;
    }
    if( ch == '*' ) { // 掛け算
      //printf("*\n");  // デバッグ用
      if( stack_n > 1 ) {
        stack_n--;
      }
      stack[stack_n-1] *= stack[stack_n];
      stack[stack_n] = 0;
    }
    if( ch == '/' ) { // 割り算
      //printf("/\n");  // デバッグ用
      if( stack_n > 1 ) {
        stack_n--;
      }
      stack[stack_n-1] /= stack[stack_n];
      stack[stack_n] = 0;
    }
    /* for( k=0; k<=stack_n; k++ ) {  // デバッグ用
      printf("%d ",stack[k]);
    }
    printf("\n"); */
  }
  //--- 出力
  printf("%d\n",stack[0]);
  //--- 終了
  return 0;
}

if( ch = '+' )と書いてしまいとても手こずった。
このプログラムでは正の整数のみしか扱えないが、'-'のあと空白なしに整数がくれば"-整数"をスタックするようにすれば負の整数も扱えるようになるかもしれない。

2014/10/21追記
数が二つだとうまく処理されないのを修正。

ティッシュを作成するアプリ(Ruby)

Rubyでティッシュを作成するだけのクソプログラムを作成してみた。

name = (0...3).map{ (65 + rand(26)).chr }.join
File.open("ティッシュ."+name,"w").close

このプログラムはティッシュ.(ランダム3文字の大文字)というファイルを作成するだけのプログラムである。
それだけです。
本来はティッシュを作った後ティッシュをゴミ箱に移動させるように考えていたが、ゴミ箱に入れるのは技術不足より断念した。