ぷらこのきろく

メモとかテストとか備忘録とか

算数の問題

ちゃんと書ける日記がここしかないのでここで。
せっかくだからてふとか使ってみよう。

ツイッターみてたらこんな問題が流れてきた。
https://twitter.com/nekonyannyan821/status/915572712596168704

で、仕事帰りの電車の中で解こうとがんばってた。。

すべてのi (1 \leq i \leq n) で i番目のカードの数字がi \\
つまり 1,2,...n とカードの数字が並んだ場合は条件を満たす。これを基準に考える。\\
んで、nのカードのどこかのカードを入れ替えたn-1通りは、条件を満たす。\\
1からn-1までのカードで、任意の2枚を入れ替えた場合、\\
小さい数字のカードは条件を満たさなくなるが、\\
そのカードとnのカードを入れ替えたらまた条件を満たす。\\
というわけで_n C _2 = \frac{n(n-1)}2\\
任意の3枚以上を入れ替えたらきっと条件を満たすのは無理っぽいから\\
全部足して\frac{n(n+1)}2\\
が答えなんじゃなかろうか。

てなことを考えてたんだけど、
問題流した人がヒントというか答え出してて
1が入るのは2通り、そのいずれにも2が入るのが2とおり、・・・
って言ってた。
なんでだーって悩んでたら
3枚以上の入れ替えでも
1,2,3,4→2,3,1,4と1つずつくるっとずらすように入れ替えて、最後に一番小さな1と4を入れ替えたら
条件満たすやん、と、家かえってお風呂に入ってから思い立ったしまった。
もちろん3以上でも成り立つ。
で、条件満たすために入れ替えるのが「1つずつくるっとずらす」だけだとしたら
 1 + (n-1) + _n C _2 + _n C _3 + ... _n C _{n-1} \\
2項定理とかで 2^{n-1}通りじゃないか。
これはヒントと合致する。
ただ、入れ替えの条件が他ではダメだということを証明してないからなんか気持ち悪い。


で、なんかくやしい。もっと方法ないか。

 n = 2のとき 2通り\\
n = k のときa _k通りと仮定したとき、n = k+1のとき増える場合は\\
  1,2,...nの順に並ぶ場合の最後に{n+1}のカードを加えた場合の1通り\\
  上の場合に、{n+1}のカードと任意のカード1枚を入れ替えた場合、n通り\\
  1,2,...nの順に並んでいないカードの最後に{n+1}のカードを加え、 \\
  n番目のカードと{n+1}番目のカードを入れ替える場合、a _k - 1通り\\
だから・・・いやちょっとまて

1~nを並べたときに、条件に合わないiが一つだけある場合
をカウントせんといかんのじゃないか。

あまりに力押しで疲れてきた。うーんやっぱりあの2通りが何個分のがいちばんスマートだよなぁ。。
とりあえず今日は疲れたので寝る。

備忘録:Java9いれてeclipse使えるようにするまで(4)

前回までで目的は達した。今回はもはやおまけ。

その(4):Hello world書いてみる。

世の中開発言語とか環境とか与えられると、とりあえずやりたくなるのがHello world
*1

プロジェクトを作る

File→New→Java Project
(画像は前回のつかいまわし)

Project名に何か入れて OK。名前にtestとか入れるのはいかにも適当なんだけど、適当なんだから仕方ない。
ちらと調べたところ、JavaJavaでそこそこのネーミング規則があるらしいが、僕はJavaはこれから勉強するということなので、全く知らない。

パッケージを作る

できたプロジェクトを右クリックし
New→Package

デフォルトでプロジェクト名と同じものが入っていた。とにかく名前を決めて OK

クラスを作る

できたパッケージを右クリックし
New→Class

クラス名を適当につけて OK

プログラムを書く

とりあえず何か書く。
僕はJavaは全く知らないので、ネットのをコピーしてきた。

プログラムについてはそのうち覚える。

実行

File→Save Allでセーブ。
javaのファイルを右クリックし、
Ran As→Java Application

下の方に何か表示された。

めでたしめでたし。

*1:ちなみに僕が普段興味ある組込みの世界は標準出力っぽいのがないので、いわゆる普通のHello worldはできないっぽい。

備忘録:Java9いれてeclipse使えるようにするまで(3)

前回の続き

その(3):eclipse設定

前回の設定のままではeclipseが動かなかった。

https://wiki.eclipse.org/Java9
僕はここを参考にした。英語で書いてあるのに僕は英語読むの苦手だけど
とりあえずかいつまんで読んでみたところ

  • Java9いれろ
  • eclipse設定ファイルに一行書き加えろ
  • Eclipse SDK をアップデートしろ

というようなことが書いてあったように見えた。ということでそのようにしてみた。

最初の、Java9いれろ、はもう入っているのでいいだろう。

eclipse設定ファイルの変更

eclipse.iniという設定ファイルが、eclipseをインストールしたディレクトリに入っている。

最後の行に、

--add-modules=java.se.ee

と書き足す。
これでeclipseを起動させることができた。

Eclipse SDKのアップデート

Help→Install New Softwareを選択


Work withのテキストボックスに

http://download.eclipse.org/eclipse/updates/4.7-Y-builds

と入力し、Add
Add Repositoryの小さいウィンドウが出るが、このまま OK


真ん中の大きなボックスにいろいろリストが出る。
Eclipse SDKをチェックして Next



(たぶん)今までインストールしたのとの競合がどうとか出てるのだと思う。
Keep my installation ...
を選び、Next
最後、ライセンスを(よく読んで)Finish
インストールが終了すると、メッセージに従いEclipseを再起動させる。

再起動後、
Help→Check for Updates
アップデートが終了するとまた再起動させられるので、指示に従う。

これでJava9が使えるようになるっぽい。

※注意
Check for Updatesしたときに、依存関係がどうのとか言われてうまくアップデートができないことがあるみたい。
どうもこれ、このソフトはあちこちで頻繁にいろんな部分のアップデートがされているんだろう。で、それが同時に起きるから
競合してるのだろう、と推測。
そのときは競合部分はCancelしておいて、きっと、時間をおくと直ってたりしそうな気がする。

Java9使えるようになったことの確認

File→New→Java Project を選択

JREの項目にJavaSE-9と出ていたらとりあえずOK。

備忘録:Java9いれてeclipse使えるようにするまで(2)

前回の続き

その(2):eclipseインストール

eclipseインストーラのダウンロード

次はここから
https://www.eclipse.org/downloads/

Get Eclipse OXYGEN
を選択。この日記書いてる時点ではこれが最新バージョンなのでそのうち名前は変わるかもだけど。

DOWNLOAD選択。たぶんミラーをうまく選択した方が速くダウンロードできるかもだけど
とりあえずこのまま。

eclipseインストール開始

ダウンロードした実行ファイルを実行

右上に"!"マークがついてたから、なんだろうと思ってクリックしてみると、アップデートができるらしい。
といあえずしておく。
(ライセンスについて聞かれたら(ちゃんと読んで)agreeとかacceptとか。以下同じ)
*1
進めるとプログラムが再起動する。今回はとりあえずJava動けばいいや、と
Eclepse IDE for Java Developers
を選択。詳しくは知らないが、恐らくWebプログラムとかしようとしたら、JavaEEとかするのかなぁ。。いずれまた今度。


大体デフォルト。僕はスタートメニューとかデスクトップとかにあまりものいれたくないので
そのあたりのチェックは外した。
で、INSTALL

※ちなみに、僕の環境ではなぜかこのままではインストールができなかった。
とりあえずBUNDLE POOLS のチェックを外すとうまくいった。

最初の起動、は、うまくいかない。
エラーが出て起動しない。

設定を行う必要がある。。

*1:ライセンスは、本来ちゃんと読まないといけない、と教えられたし、実際そうなんだけど、面倒くさいので僕はよく省略してる。 なんかあったらネットの中の人が騒ぐだろうし。でもよい子はマネしないように。

備忘録:Java9いれてeclipse使えるようにするまで(1)

ふと思い立って、eclipseを入れてみようと思った。
厳密には数年前に入れてたらしいが、この際ちゃんと使えるようにしてみようと、クリーンインストールに挑戦。
その顛末を記録しておく。

その(1):Javaをインストールするまで

Javaインストーラのダウンロード

まずはここから
http://www.oracle.com/technetwork/java/javase/downloads/index.html

JDKを選択

ライセンスを(ちゃんと読んで)Acceptを選ぶとダウンロードできる

で、ダウンロードした実行ファイルを実行してインストール開始

Javaインストール開始

開始

とりあえずデフォルト。
インストールフォルダもデフォルト

で、とりあえずインストール完了

環境変数の設定

どうも、他のサイト見てたら、環境変数の設定をするとよいらしい
ということで僕の環境(Windows7)の場合

コントロールパネル→ユーザーアカウント→環境変数の変更
ユーザー環境変数のPathに、
C:\Program Files\Java\jdk-9\bin
を追加

ちなみにPathは、";"(セミコロン)で区切る。この仕様たぶんMS-DOSのときからのなごり。
ちなみにちなみに他のサイトではシステム環境変数を使っていたんだけど、
僕の感覚ではあまりそれやりたくない。システムはあまりいじりたくない感じ。
ユーザーの環境変数でうまくいきそうだし、それでいいと思う。

動いたかどうかの確認

コマンドプロンプトを起動
(スタートのプログラム一覧から、アクセサリ→コマンドプロンプト)

で、
java -version
と打って、リターン。

java9のバージョンが表示されたら成功。

qsortを再帰を使わずに書く

そういうお題が某所で提供されたので、せっかくだから解いてみる。
ちなみに出題者の方は僕より数日早く自分で解かれたようだった。。。

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


#define ARR_SIZE     (20)
#define SHUFFLE_NUM  (1000)

typedef struct jobs {
  struct jobs* prevjob;
  int* start;
  size_t size;
} job_t;

void testqs(size_t size);
void printarr(int* arr, size_t size);
void myqsort(int* arr, size_t size);
int getpivot(int a0, int a1, int a2);

int getpivot(int a0, int a1, int a2)
{
  int retval = 0;
  if(a0 > a1) {
    if(a1 > a2) {
      retval = a1;
    }
    else if(a0 > a2) {
      retval = a2;
    }
    else {
      retval = a0;
    }
  }
  else if(a0 > a2) {
    retval = a0;
  }
  else if(a1 > a2) {
    retval = a2;
  }
  else {
    retval = a1;
  }
  return retval;
}

void myqsort(int* arr, size_t size)
{
  int* head;
  int* bottom;
  int sortsize;
  int pivot;
  int tmp;

  int* sav_head;
  int* sav_bottom;
  
  job_t* nowjob;
  job_t* addjob;
  job_t* lastjob;

  addjob = (job_t*)malloc(sizeof(job_t));
  addjob->prevjob = NULL;
  addjob->start = arr;
  addjob->size = size;
  lastjob = addjob;

  while(lastjob != NULL) {
    nowjob = lastjob;

    head = nowjob->start;
    sortsize = nowjob->size;
    bottom = head + sortsize - 1;
    
    sav_head = head;
    sav_bottom = bottom;

    lastjob = lastjob->prevjob;
    free(nowjob);

    if(sortsize < 2) {
    }
    else if(sortsize == 2) {
      if(*head > *bottom) {
        tmp = *head;
        *head = *bottom;
        *bottom = tmp;
      }
    }
    else {
      pivot = getpivot(*head, *(head+1), *(head+2));
      while(head < bottom) {
        if(*head > pivot) {
          while(head < bottom) {
            if(*bottom <= pivot) {
              tmp = *head;
              *head = *bottom;
              *bottom = tmp;
              bottom --;
              head++;
              break;
            }
            else {
              bottom --;
            }
          }
        }
        else {
          head++;
        }
      }
      while(head <= sav_bottom) {
        if( *head> pivot) {
          break;
        }
        head++;
      }
      if(head > sav_head) {
        addjob = (job_t*)malloc(sizeof(job_t));
        addjob->prevjob = lastjob;
        addjob->start = sav_head;
        addjob->size = head - sav_head;
        lastjob = addjob;
      }
      if(head < sav_bottom) {
        addjob = (job_t*)malloc(sizeof(job_t));
        addjob->prevjob = lastjob;
        addjob->start = head;
        addjob->size = sav_bottom - head + 1;
        lastjob = addjob;
      }
    }
  }
}
    
void testqs(size_t size)
{
  int* arr;
  int i;
  int a, b;
  int tmp;
  
  arr = (int*)malloc(sizeof(int) * size);
  memset(arr, 0, sizeof(int) * size);
  
  for(i = 0; i < size; i++) {
    arr[i] = i;
  }
  
  for(i = 0; i < SHUFFLE_NUM; i++) {
    a = rand() % size;
    b = rand() % size;
    tmp = arr[a];
    arr[a] = arr[b];
    arr[b] = tmp;
  }
  printarr(arr, size);
  myqsort(arr, ARR_SIZE);
  printarr(arr, size);
  free(arr);
}

void printarr(int* arr, size_t size)
{
  int i;
  
  for(i = 0; i < size -1; i++) {
    printf("%d, ", arr[i]) ;
    if ( i % 20 == 19 ) {
      printf("\n");
    }
  }
  printf("%d\n", arr[size - 1]);
}

int main(int argc, char** argv)
{
  int i;
  for(i=0; i< 10; i++) {
    testqs(ARR_SIZE);
  }
  return 0;
}

即席で作ったからコメント一切なし、
即席で作ったからmallocの返り値チェックなし、
作者の腕が悪いからコードは汚い

まあ、(たぶん(※))動いたからよしとしよう。

(※)適当なテストプログラム組んでみたらちゃんとソートされた。

walk NewBitmapFromImage()

今日遊んだコードはこれ

package main

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)
import (
	_ "go.image/bmp"
)
import (
	"fmt"
	"image"
	"image/color"
	"os"
	"log"
)

func imgfromfilename(filename string) (img image.Image, err error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	img,_, err = image.Decode(file)
	if err != nil {
		fmt.Println("Decode")
		return nil, err
	}
	return img, nil
}

type myimage struct {
	img image.Image
}
func (mi myimage) ColorModel() color.Model {
	return mi.img.ColorModel()
}
func (mi myimage) Bounds() image.Rectangle {
	return mi.img.Bounds()
}
func (mi myimage) At(x, y int) color.Color {
	col := mi.img.At(x, y)

	r, g, b, _ := col.RGBA()
	return  color.RGBA{uint8(r+0xff), uint8(g)^0xff ,
		uint8(0x88- uint8(b)) , uint8(0xff)}
}
	
func main() {
	var iv *walk.ImageView
	
	img, err := imgfromfilename("../tombo_big2.bmp")
	if err != nil {
		log.Fatal(err)
		return
	}

	myimg := myimage{img}

	bitmap, err := walk.NewBitmapFromImage(myimg)
	if err != nil {
		fmt.Println("NewBitmapFromImage")
		log.Fatal(err)
		return
	}
	imgsize := bitmap.Size()
	
	MainWindow{
		Title: "hello",
		Size: Size{
			Width: imgsize.Width,
			Height: imgsize.Height,
		},
		Layout: VBox{
			MarginsZero: true,
		},
		Children: []Widget {
			ImageView {
				AssignTo: &iv,
				Image: bitmap,
				MaxSize: Size{
					Width: imgsize.Width,
					Height: imgsize.Height,
				},
				MinSize: Size{
					Width: imgsize.Width,
					Height: imgsize.Height,
				},
			},
		},
	}.Run()
}

下準備

このコードを動かす前に、ちょっとだけ下準備がいった。
goの標準ライブラリでは、bmpは扱わなくなったっぽい
というわけで、それをとってこようとがんばってみる。
んで、ここを探すと、

hg clone https://code.google.com/p/go.image/ 

ってやれって書いてあって、もちろんhgなんてコマンド入っていないわけで、ここからとってきた。僕が入れたのは、Setup installer の does not admin rights というの。adminで入れるのは極力避けたい。
で、適当にインストールして、hgコマンドでとってきた。とってきた先のディレクトリは、
%GOPATH%\srcの下。とりあえずこの辺においておいた。

コードの説明

import宣言で、さっきとってきたgo.image/bmpを読み込む。
どうも読み込むだけで、image.Decode()とすれば、bmpだったらそのデータを読み込んでくれた。なので、"_"がついている。

imgfromfilename()で、ファイルからimage.Imageのデータに変換。
それだけでは面白くないので、自分でmyimage{}構造体を作って、変換してみた。
このやり方は、チュートリアルの練習問題にあったので、それを真似てやってみた。
そうやって作った、image.Image型のデータを、walk.NewBitmapFromImage(myimg)として*Bitmap型に変換。これはwalk.Image型としてImageView構造体のImageにそのままつっこめる。

今まで面倒くさかったのでやってなかったエラーチェックを適当にしているが、うまく動かなかった名残。
ちなみにうまく動かなかった原因は、bmpファイルがサポートされてない形式のものだったかららしい。一度gimpで読み込んでエクスポートして、その際に、互換性のところの、「色空間の情報を書き込まない」にチェックを入れたらうまくいった。なので、"tombo_big2.bmp"となってる。

って、ここまでやってきたが、image.Image型を通さなくても実は*Bitmap型を適当にいじったりできないんかなぁ。。
そのうちやってみよう。