読者です 読者をやめる 読者になる 読者になる

kentsu.dat

何かその時の興味でいろいろする人。最近はScala使ってる。アルゴリズムと自然言語処理、深層学習が大好き。

自分なりの、プログラミングを楽しむためのベストプラクティス

はじめに

大学や専門学校、高校中学や老若男女問わず、これからプログラミングを始める初心者の人がどうすればプログラミングを楽しめるか。
案外むずかしいこの話題に関して、自分の経験を踏まえた自分なりのベストプラクティスをまとめてみた。


自分は高校入学と共にプログラミングを始め、独学でJavaScala,C,Pythonなどを学びプログラムを組んできた。
本来、この手のものは誰かに教えてもらう方がいいのだが、ほぼ独学でスキルを磨いてきた経験が多少なりとも役立てばいいと思う。


この記事はあくまでも個人的な意見であり、プログラミングを楽しむにはどうしたらいいかということをまとめただけなので、プロのマサカリはご遠慮願いたい。
もしそれでもマサカリを投げたくなったらこのブログではなく、私のgithubにはいくつか進行系のプロジェクトがあるのでそちらにお願いしたい。

github.com



この記事は楽しむことに重きをおいている
楽しまなければ、いくら魅力的でもそれを実感せずに終わってしまうからだ。


それでは、はじめよう。

プログラミング言語を選ぶ

プログラミングを楽しむ上でこれがまず最初の難関になるだろう。
そして、ここで選択を誤ってしまうと途端にプログラミングがとてもつまらないものになってしまう。
しかもたちが悪いことに、プログラミングを実際にその言語で行うまで自分が誤った選択をしたと気付けない。


楽しさには個人差があるのでここではざっくりと「こういう言語がいいのでは」ということをまとめる。


プログラミングを楽しみたい人には2つのタイプがあるように感じる。

  • 真っ黒な画面に文字が出ること自体を面白いと感じる人
  • 具体的な何かソフトウェアを作り上げ面白いと感じる人


このどちらに当てはまるかで言語選択は大きく変わる。

真っ黒な画面に文字が出る。これを面白いと感じる人


このタイプに当てはまる人は迷わず「C言語」や「C++」といった言語を選ぼう。


このタイプに当てはまる人は非常に少ないがそういった言語を選ぶことで情報工学のあれこれに触れることができる。
それ自体を面白いと感じ、自分で勉強をする事が苦ではなくなるだろう。


初めに紹介した言語でなくても、このタイプの人は「この言語やってみたい」というものを選んでもきっと楽しめるだろう。

なのでここではこれ以上取り上げない。

具体的なソフトウェアを作り上げ面白いと感じる人


このタイプの人は間違っても「C言語」や「C++」といった言語を選択してはならない。
よくネットでは「プログラミングするならCから始めろ」や「いいやアセンブリから始めろ」という過激派な意見を多々見るがこれに惑わされてはいけない。
そういった意見はあなたがプログラミングを始め、楽しむことを阻む。


実際、あれらの言語は環境にもよるが目でみてわかるものを作りにくい傾向にある。
なので、画面に文字を表示するだけのどこが面白いのかとすぐに飽きてしまうだろう。


ただ、このタイプに当てはまる人は大勢いるので、そういった人のためにおすすめの言語をいくつかまとめる。

  • Java
    • GUI(メモ帳などウィンドウとしてでるプログラム)が非常に作りやすい
    • Androidアプリケーションも作れるので目で見てわかる成果を作りやすい
  • Python
    • 最近注目の言語。文法が短く手軽に書ける。簡単。
    • GUIもWebもいける言語
    • 画像を扱ったりもできるので目で見てわかるものを作りやすい
  • Ruby
    • 日本発祥の言語。Pythonと似たような部分が多い。
    • 日本語の情報が多く困ったことがあればググれば大抵解決できる
  • JavaScript
    • webブラウザで動作する言語。
    • html/cssなど簡単なのと一番目で見てわかる成果を作りやすい。


ここで取り上げた言語にはオブジェクト指向と言われるものが備わっている。
これはたいていの言語にあり、どれを選んでもきっとその後の助けにもなるだろう。

プログラミングを実際にしてみる

プログラミング言語を選んだら実際にプログラムを作って欲しい。
ただここで「Hello World!」を表示させ、画面にでる。これを面白いと思ったからといって容易に言語を変えないで欲しい。
それは、一時の感情に過ぎない。


実際はそれより多くの時間を使うことになるのだから。


プログラミングをする際は、できれば書籍で特に入門書を一冊持っておくのがいいだろう。
ネット上にも情報はたくさん転がっているが書籍を一冊もつことを強くすすめる。


実際にプログラムを組むといっても、初めは基礎的な文法を学ぶことになるだろう。
それをつまらないと思ったなら、いきなりGUIなどのアプリケーションを作成しながら学んでいくのもいい。
ネットで調べて、拾ったコードを見様見真似で書いてもいい。
コピペしてもいい。


とにかくなにかプログラムを作ってみよう。


ここで重要なのは諦めないこと。
諦めてしまっては何も面白いとも思えない、諦めずに苦戦しながらも何か一つでいい、簡単なものでいいのでつくり上げる
完成した頃にはとてつもなくプログラミングを面白く感じるだろう。

作るまでに、コピペしようが写経しようがどれほど汚いコードを書こうが関係ない。
大切なのは楽しむことなのだから。

勉強してみる

何か最初に作って、おもしろいと感じたならもう少し自分が使ってる言語や、情報系の関連技術について勉強してみよう。
今までに身につけた知識とつながりが感じられさらにおもしろく感じるだろう。


ここでは、どうやって勉強したらいいか取り上げる。


実際にプログラミングや情報系の関連技術の勉強をしていくなかで本やネットの情報を参考にすることだろう。
そういったとき、陥りやすいのが無知や周囲の出来る人と自分を比較し「自分には知らない事がたくさんある。ぜんぜん出来ない。」といったネガティブな感情である。


自分の無力さ、無能さを実感することがあるだろうがそれを気にしてはいけない。
これは誰もが通る道であり、あなたがすごいと思う人たちも皆通ってきた道であるから。


知らないことわからないことがいくらあろうが今は気にせず自分のペースで勉強しよう。

本やネットの情報を元に勉強する時

こういった場面で気をつけたいことがある。


初めたばかりの人は特にいくらテキストを読んでも「なんじゃこりゃ」となりやめてしまうことがある。


せっかくここまで来たのにそこでやめてしまってはもったいない。


そこでおすすめの勉強法がある。


わからない、読んでも理解できない。
こういったものが出てきたとき、実際にコードにして実行してみよう。


必ずしも読んで頭で理解する必要はない。
実際に動かし、自分のもつ疑問を実際の動作から感じとり解消しよう。


これは理解が止まったとき、無理に理解しようとするよりよっぽど有効な手段である。

一般的である必要はない

ここまで紹介したことはあまり一般的ではない。


学校などでは通常
CやってJavaやって…。
みたいにやり、学校が決めたとおりの手順で勉強する。


これは大抵の場合、あなたが楽しめるようなものではない。


そういったとき別なプログラミング言語に取り組んだり、自分でガンガン先に進んだりして欲しい。
自分のペースで勉強したとしても実際そんなに影響はない。


むしろ、無理して学校が決めたり他人が決めた手順でやったほうがその後に影響しやすい。


面白いと感じたなら、プログラミングを楽しみたいと感じたならぜひとも積極的に知識やスキルを身につけて欲しい。


最後に


ここまでくればプログラミングが楽しくなったり、情報系関連技術を実際に使うことが楽しく感じられるだろう。


最後に
あなたが実際にプログラミングをはじめたときや楽しみたいと思ったとき、こんなに上手くはいかないだろう。それが普通である。


それはこの記事を書いた自分も同じであった。
今まで嫌になるほどエラーとバグと格闘してきた。
幾度と無く、失敗と挫折を繰り返してきた。


ただそんな自分でも、楽しむことでなんとかある程度のプログラムを作れるスキルを身につけることができた。


失敗や周囲の評価を恐れず、型にはまらずあなたなりにとにかく楽しんで欲しい。
自分が楽しいと思うことをひたすらにやってほしい。


そうしてプログラミングを楽しんでくれる人が増える事を切に願う。

日本語版NetBeans8.2をUbuntuにいれてみた

なぜかNetBeansをいれることになった

友達曰く、「NetBeansが英語なのとプロジェクトを開けない」とのことで実際に検証してみた。
普段はVSCodeかVimとsbtでScala,Javaしか書かない人間のUbuntuにはそんな便利なもの入ってるわけもなく
実際に導入しながらそれらを試してみた。

NetBeans日本語化できないのか?

最初から日本語化されてるのあったっぽい

ja.netbeans.org

ダウンロードした

ダウンロードして、homeディレクトリにnetbeans-8.2-javase-linux.shみたいなファイルを持ってくる。

インストールした

次のコマンド打ったらこんな出力でた

$ sh netbeans-8.2-javase-linux.sh 
インストーラを構成しています...
システムでJVMを検索しています...
インストール・データを抽出しています...
インストーラ・ウィザードを実行中...

これでインストーラが起動したので

f:id:RabbitFoot141:20170516231435j:plain

どんどん次へなり、進むなりを押していく

すると最高に嫌な予感がする。
こんなのが出てきた。

f:id:RabbitFoot141:20170516232508j:plain

これ無視し続けて、なんとかインストールすると

起動はするが、プロジェクト開くときにこんなのがでた

f:id:RabbitFoot141:20170516233126j:plain

まぁ開けないわな。

開き方を変えた

netbeansをいれたディレクトリに移動する

$ cd netbeans-8.2

そこでさらにbinディレクトリに移動する。

~/netbeans-8.2$ cd bin
~/netbeans-8.2/bin$

ここまできたら、次のコマンドを実行してjdkとやらの場所を確認する

~/netbeans-8.2/bin$/usr/sbin/update-java-alternatives -l
java-1.8.0-openjdk-amd64       1081       /usr/lib/jvm/java-1.8.0-openjdk-amd64
java-8-oracle                  1077       /usr/lib/jvm/java-8-oracle

みたいなことになるから、jdkのほうをコピペして次のコマンドで実行する

~/netbeans-8.2/bin$./netbeans --jdkhome /usr/lib/jvm/java-1.8.0-openjdk-amd64

これで使えるようになった(はず)。

それ以外で

UbuntuならUbuntu Softwareからインストールすると楽。
英語だけど。

最後に

一回使ってみたけど、やっぱりNetBeans使いにくい。

【メモ】sbtで自作ライブラリを使えるようにした話

とりあえず公開したかった。

なんか公開したかった。
sbtで使えるようにしたかった。

何をやったか

とりあえず次のサイトを参考にしてあれこれした

qiita.com
qiita.com
d.hatena.ne.jp


具体的には

  • ライブラリをビルドする
  • github pagesを作成しそこにビルドしたやつをぶん投げる
  • wgetでテストする
  • sbtで使えるかテストする

ライブラリをビルドする。

とりあえず、sbtプロジェクトに作成してるであろうBuild.scala,build.sbt的なあれこれに次を追加する。

Build.scalaならsettingsの中に突っ込んでください。
それ以外のname,version,scalaVersionはもうすでに設定したものとする。

publishTo := Some(Resolver.file("名前",file("jar,pomなどを作成するディレクトリを指定"))(Patterns(true, Resolver.mavenStyleBasePattern)))

ここで一度プロジェクトをコンパイルする。

$ sbt compile


これでokなら次を実行する

$ sbt publish

するとさっき指定したディレクトリに「名前」のディレクトリとその直下に「名前_ScalaVersion」のディレクトリが生成されている

github pagesを作成しそこにビルドしたやつをぶん投げる

公開したいライブラリがgithubのレポジトリにあるとして、そのレポジトリにgh-pagesというブランチを作る。
とりあえずそこにindex.htmlを投げる。

そしていつもどおりgh-pagesにpushする。

その勢いでさっきビルドしたあれこれをぶん投げる。
手順はこれで終わり。

wgetでテストする

次のコマンドを走らせてdlできればok

 wget https://[username].github.io/reponame/projectname/projectname_scalaVersion/version/projectname_scalaVersion-version.jar

これでダウンロードできないなら何かしら失敗しているか、gh-pagesの反映に時間がかかることがあるので最初にリンクを張ったサイトをみてどうにかしてみる。

sbtで使えるかテストする

適当にプロジェクト作るかどうにかして別のBuild.scalaで使うには次のようにする

//ライブラリを追加するところに
"projectName" % "projectName_scalaVersion" % "Version"

//resolverを作って次を記述
resolvers += "Maven Repo on github" at "https://[username].github.io/projectName/"


これでダウンロードできる(はず)

Newton-Raphson法と単位円内接正多角形を使った円周率近似をScalaでやってみた

やってみた

C言語縛りは面白くないので例によってScalaでやってみた

こんなやつをコードにした

まずNewton-Raphson法は次の式におけるxの値を求める

 \displaystyle
f(x) = g(x) - C = 0

このあと登場するけど、単位円内接正多角形を使う近似では漸化式をつかっていくわけだけども
その中で平方根を計算しないといけないのでCを任意実数定数として関数g(x)を次のようにする

 \displaystyle
g(x) = x^2

すると次の式におけるxを近似的に求めることになる

 \displaystyle
f(x) = x^2 - C = 0 \\
x^2 - C = 0 \\
x^2 = C

Newton-Raphson法ではこれを次の式を満たす様に微分を使いながら近似していく

{ \displaystyle
x_{n+1} = x_n - \frac{f(x_n)}{\frac{df}{dx}(x_n)}
}

ここまでNewton-Raphson法

次に単位円を用いて円周率を求める。
しかし、円周がわからない。
これは円周率が不明であるためである。

そこで単位円内に内接正多角形を作って円周とみなす。
これは漸化式で表現でき正n角形のnが大きくなればなるほどその周の長さが円周の長さに近づく。

その内接正多角形の一辺の長さが次の式となる
{ \displaystyle
L_{n+1} = \sqrt{ 2-2\sqrt{1-(\frac{L_n}{2})^2} } \: or \:  L_{n+1} = \sqrt{2-\sqrt{4-(L_n)^2}}
}

というわけでコードにしてみた

実際に書いたコード

object calcPI{

    val max = 20

    def main(args:Array[String]):Unit = {
        var Ln = newtonRaphson(2)//L_1

        var n = 0
        var pow = 2
        while( n < max ){
            println( pow * Ln )
            Ln = newtonRaphson(2 - newtonRaphson(4-Ln*Ln))
            n += 1
            pow *= 2
        }
    }

    def newtonRaphson(c:BigDecimal):BigDecimal = {
        var x:BigDecimal = c
        var dx:BigDecimal = -func(x,c) / dfunc(x)

        while( 1.0e-16 < dx.abs  ){
            x += dx
            dx = -func(x,c) / dfunc(x)
        }

        return x
    }

    def func(x:BigDecimal, c:BigDecimal):BigDecimal = x*x - c
    def dfunc(x:BigDecimal):BigDecimal = 2.0*x
}

これを実行して、出力結果をdatファイルにおとしてgnuplotでグラフにするとこんな感じになる

f:id:RabbitFoot141:20170504120319p:plain

BigDecimal使ってはいるけど精度的にはまだまだかなと思うけどある程度できた。

Newton-Raphson法を用いた円周率近似

Newton-Paphson法の基礎原理

Newton-Raphson法とは次の式を満たすxの値を見つけるアルゴリズム
{ \displaystyle
f(x) = g(x) - C = 0
}
ここではg(x)を任意の微分可能な関数としてCを実数定数とする。
つまりNewton-Rapshon法は次の式を満たすxの値を見つけるアルゴリズムとなる。

{ \displaystyle
g(x) = C
}

つまり以下の様にg,Cが与えられた時は2の平方根を求めることになる。

{ \displaystyle
g(x) = x^2, C = 2
}

実際の計算

基礎原理はうえで紹介したので実際に解を近似して求める。というのも上記の式を満たすxがすぐに正確に見つかるわけではないことによる。
そこで与えられたf(x)を一回微分して接線の方程式を求め、その接線とx-軸の接点におけるx座標で再びf(x)に戻り微分し接点のx座標を求める…。
これを再帰的に繰り返すことで求めたいxに近似していくこととなる。
その漸化式は次のようになる。

{ \displaystyle
x_{n+1} = x_n - \frac{f(x_n)}{\frac{df}{dx}(x_n)}
}

この漸化式をC言語を用いたコードとして表現していく。
ここでは平方根を求めることにする。

コード化する

ひとまず次のプログラムをベースにする。

#include<stdio.h>

int main(){
    return 0;
}

ここで関数fとそれを一回微分したdfを関数として作る。

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

//プロトタイプ宣言
double Func(double x,double C);//変数xとCが必要となる
double dFunc(double x);//fを微分しているのでxのみ必要

int main(){
    return 0;
}

double Func(double x, double C){
    return x*x - C; //x^2-Cを計算して返す
}

double dFunc(double x){
    return 2.0*x; //2xを返す
}

これで準備は出来た。

次に微分して…。となるがCで微分を扱うのは難しいので数学的に考えてfとxのみの式に直す。
それは以下になる。

{ \displaystyle
\frac{df}{dx}(x_n) = \frac{f(x_n)}{x_n-x_{n+1}}
}

というわけでNewton-Raphson法を用いて平方根を求める。ここでは誤差が{10e-6}になるまで続けることにする。

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

//追加した
#define EPS 10e-6

//プロトタイプ宣言
double Func(double x,double C);//変数xとCが必要となる
double dFunc(double x);//fを微分しているのでxのみ必要

double Newton(double C);//平方根を求めたい値を実数で受け取る

int main(){

    printf("%12.10f\n",Newton(2) );

    return 0;
}

//Newton-Rapshon法を用いてcの平方根を求める。
double Newton(double C){
    
    double x = C;
    double dx = -Func(x,C)/dFunc(x);
    
    while( fabs(dx) > EPS){
        x += dx;
        printf("%12.10f\n",x);
        dx = -Func(x,C)/dFunc(x);
    }
    return x;
}

double Func(double x, double C){
    return x*x - C; //x^2-Cを計算して返す
}

double dFunc(double x){
    return 2.0*x; //2xを返す
}


これで平方根をNewton-Raphson法を使って求めることができる。
ただし、誤差があることに注意。

円周率近似

円周率近似も漸化式を用いて行う。
http://oto-suu.seesaa.net/article/291513400.html
上記のサイトがそれを紹介しているが半径が{\frac{1}{2}}なので、半径を単位円において考えることにする。
基本的には正n角形の周を求め円周に近似していくことになる。

その場合、漸化式は次のようになる。
{ \displaystyle
L_{n+1} = \sqrt{ 2-2\sqrt{1-(\frac{L_n}{2})^2} } or L_{n+1} = \sqrt{2-\sqrt{4-(L_n)^2}}
}

ソースコードにする

これをソースコードにするとこうなる

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

#define EPS 1.0e-8
#define POW 2

double Newton(double);
double Func(double, double);
double dFunc(double);

int main(){

    double Ln = Newton(2.0);//L_1 = sqrt(2)
    printf("%12.10f\n",Ln);
    int n = 1;
    int pow_base = 2;
    int n_max = 20;

    while( n < n_max ){ 
        
        printf( "%12.10f\n", pow_base * Ln );
        Ln = Newton( 2-Newton(4 - pow(Ln, 2)) );
        n += 1;
        pow_base *= POW;

    }

    return 0;
}


//平方根を求める
double Newton(double C){
    
    double x = C;
    double dx = -Func(x, C) / dFunc(x);
    
    while( fabs(dx) > EPS ){
        x += dx;
        dx = -Func(x, C) / dFunc(x);
    }

    return x;
}


double Func(double x, double C){
    return x*x-C;
}

double dFunc(double x){
    return 2.0 * x;
}

これで円周率の近似値が求められた。

githubでコミットしても芝生が生えなかったわけ

昨日、githubの自分のレポジトリにコミットしてたら唐突に芝生が生えなくなった。

それで色々ググった結果

  • masterブランチじゃないとだめ
  • ローカルレポジトリの登録アドレスがgithubアカウントのメールアドレスになっていないとだめ
  • forkしたやつもだめ

みたいなあれこれが書いてあって、それ以外の原因は見つからなかった。

がしかし、自分の環境ではmasterブランチにコミットしていたし、メアドも合ってるし、自分で作成したレポジトリだしってことで
沼に陥ったので、github supportにこれらの問題をぶん投げた。

すると返信があって

「ラグってるだけだと思うから、24時間以上して芝生生えなかったらまたメールしてね」

と来たので今朝見たら、本当にラグってただけだった。

なんか芝生もすぐに反映されなくて、数時間ラグることもあるらしい。

Java使いのScala入門 〜Scala入門のはじめの一歩〜

Scala入門のはじめの一歩

これから何回かに分けてScala入門についての記事を書いていこうと思う。
教材はScala スケーラブルプログラミング[第3版]を元にJavaとの違いをまとめていく。


今回は「Scala入門のはじめの一歩」ということで、Scalaとは何か。ということをまとめる。

Scalaとは何か

Scalaとは、使うユーザに合わせて大規模システムや小規模システムを構築することが可能な
極めて広範囲のプログラミングニーズに応える言語である。

Scalaは標準javaプラットフォームのうえで動作しすべてのJavaライブラリを相互運用できる。
これはScalaがBetter Javaと言われる要因の一つとなっている。

またScala関数型言語の特徴を持っている。
それに加えて、Javaと互換があるのでオブジェクト指向言語的特徴も持っている。

この2つのプログラミングスタイルを持つが故にScalaは広範囲のプログラミングニーズに応えることができる。


それをScala スケーラブルプログラミングでは以下のコードを例に挙げて説明している。

var capital = Map("US" -> "Washington")
capital += ("Japan" -> "Tokyo")
println(capital("Japan")) //Tokyo

Scalaでは連想マップをつかってこのように書くことができる。
これを見たJavaユーザは驚くかもしれないが、恐ろしいほどに短いコードで
一見するとそれこそ、python,ruby,perlのようなスクリプト言語的なコードになっている。

同じコードをJavaで書こうとすると、もっと長く冗長で細かい条件を設定する必要がある。


ただScalaの強さはそれだけではない。
このように簡単にMapをかけるがこれはデフォルトの仕様に過ぎず
必要に応じてhashmapやtreemapなどなどScalaでサポートされているものに関して
もっと細かく設定を拡張、修正できるようになっている。

つまりScalaJavaと比べて恐ろしく柔軟で書きやすい言語であると言える。

Javaと互換性を持つこと、拡張できるということ

Javaとの互換性はこの記事内で詳しく紹介するが前述した特徴をJava比較するのではなく
ScalaJavaと互換性を持つということがどういうことなのかをここでは簡単にまとめる。

例えば次のscalaライブラリークラスを使用すると想定する。

scala.BigInt

これはBigIntegerといえばscalaに馴染みのない人にも伝わると思うが
オーバーフローやアップアラウンドが発生せず扱える数の上限が決まっていない(正確には決まっているが)整数の型である。

これを使って、よくオーバーフローする階乗の計算をやってみる。

def fact(x:BigInt):BigInt = 
  if (x == 0) 1 else x*fact(x-1)

これを実行するとこうなる

res:BigInt = 265252859812191058636308480000000

ここで示したようにBigInt型を使って整数リテラルのように演算できるので一見組み込み型のようだが
ここで使ったクラスはScalaの標準ライブラリーで定義されているクラスに過ぎない。

もし仮にこのようなクラスがなかったとしても自ら実装することでScalaプログラマは簡単にこれらの作業を行うことができる。


それが面倒だというなら、Javaと互換性があることが大きな武器となる。
Javaと互換性があるので次のような実装を考えることができる。

import java.math.BigInteger //これがすごく重要

def fact(x:BigInteger):BigInteger = {
    if (x == BigInteger.ZERO)
        BigInteger.ONE
    else
       x.multiply(fact(x.subtract(BigInteger.ONE)))
}

このコードを実行してもはじめに紹介したコードの実行結果と同じ実行結果が返ってくる。

つまりjavaのライブラリであっても使用できる。

この機能があるが故にScalaの、あたかもネイティブサポートしてこのような型が使えるかのように感じられる。


もし必要な型がscalaになく,javaにあるのなら独自実装せずにこのようにJavaから持ってくることもできる。

これがScalaJavaと互換性を持つことと、拡張性に優れていることを表している。

ここまでのまとめ

ここまで出てきたScalaの特徴をまとめる

これらからScalaをもっとざっくりとまとめると
Javaと互換性があるが簡潔で高水準の抽象を備えた強い静的型付け言語と言える。

つまり「Better Java