プログラマメモ2

2009-11-29

JTableを使う練習


Javaです。
JTableを使った簡単なツールを書くときいつも時間かかってます。
毎回グーグルさんで調べたり 、swingなら、Java Swing Tips - てんぷらメモで調べてます。

組み込みDBを使ってデータをderby,h2とかにもたせて使うととか、csv,tsvでデータをもたせるとかJTableを手軽に使えたほうが何かと便利ですね。

package ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SortOrder;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

/**
*
* テーブルを使ったUIのプロトタイプを手軽に作りたい目的用途 いい方法が思いつかない。
*
*/
public class PanelTable extends JPanel {

/**
* 参考
* http://terai.xrea.jp/Swing/StripeTable.html
*
*/
class StripeTableRenderer extends DefaultTableCellRenderer {
Color evenColor = new Color(244, 247, 251);

public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if(isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
}else{
setForeground(table.getForeground());
setBackground((row%2==0)?evenColor:table.getBackground());
}
setHorizontalAlignment((value instanceof Number)?RIGHT:LEFT);
return this;
}
}

public class Column {
String s;
int w;

public Column(String s, Integer w) {
this.s = s;
this.w = w;
}

public String toString() {
return this.s;
}
}

public Vector<Column> toColumns(Object[][] os) {
Vector<Column> columns = new Vector<Column>();
for (Object[] os2 : os) {
Column column = new Column((String) os2[0], (Integer) os2[1]);
columns.add(column);
}
return columns;
}

final JTable table = new JTable() {
{
setDefaultRenderer(Object.class, new StripeTableRenderer());
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
};
JScrollPane scrollPane;
{

this.scrollPane = new JScrollPane(table);
setLayout(new BorderLayout());
add(this.scrollPane, BorderLayout.CENTER);
}

/**
* vecOfvecが行指向の場合 行指向のデータの持ち方
*
* @param vecOfvec
* @param columns
*/
public void setModel_RowBase(final Vector<Vector<String>> vecOfvec,
final Vector<Column> columns) {

SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
DefaultTableModel model = new DefaultTableModel();
model.setDataVector(vecOfvec, columns);
setModel(model);

for (int i = 0; i < columns.size(); i++) {
Column c = columns.get(i);
TableColumn tableColumn = table.getColumnModel().getColumn(
i);
tableColumn.setHeaderValue(c.s);
tableColumn.setPreferredWidth(c.w);
}

}
});

}

/**
* vecOfvecが列指向の場合 列指向のデータの持ち方
*
* @param vecOfvec
* @param columns
*/
public void setModel_ColBase(final Vector<Vector<String>> vecOfvec,
final Vector<Column> columns) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
DefaultTableModel model = new DefaultTableModel();

for (Vector<String> v : vecOfvec) {
model.addColumn("", v);
}
setModel(model);
for (int i = 0; i < columns.size(); i++) {
Column c = columns.get(i);
TableColumn tableColumn = table.getColumnModel().getColumn(
i);
tableColumn.setHeaderValue(c.s);
tableColumn.setPreferredWidth(c.w);
}

}
});

}

/**
* 参考
* http://terai.xrea.jp/Swing/TriStateSorting.html
* @param model
*/
protected void setModel(TableModel model) {

this.table.setModel(model);

TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(
model) {
@Override
public void toggleSortOrder(int column) {
if (column >= 0 && column < getModelWrapper().getColumnCount()
&& isSortable(column)) {
List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
if (!keys.isEmpty()) {
SortKey sortKey = keys.get(0);
if (sortKey.getColumn() == column
&& sortKey.getSortOrder() == SortOrder.DESCENDING) {
setSortKeys(null);
return;
}
}
}
super.toggleSortOrder(column);
}
};

this.table.setRowSorter(sorter);

}
}




2009-11-24

モンティ・ホール問題 その1


正直、いまだによく理解できてない確率問題 モンティ・ホール問題です。


プログラム書いたらうーんたしかにそうだなーと思うところありだけど、直感的にはどうも....

で、どうして再びこの問題を考えることにしたというのは、
たまたま―日常に潜む「偶然」を科学する
田中 三彦
4478004528

この本にのっていたからだけど、最近の確率を扱った本ではとりあげられますね。

詳しい説明はwikipeiaをみればわかりますが、自分の頭で「わかった」という感じになるまでちょい時間がかかりました。

愚直にシュミレートしてみて結果をおっていく過程でなんとなく「わかり」ました(と思う)。

プログラムは3つの箱のひとつにランダムに「あたり」を入れて、再びランダムに箱を選ぶパターンと、
ランダムに選んだ箱以外の箱を司会のモンティが開いてその逆を選ぶというパターンにしてみました。

最初のパターンは1/3となりますね。
つぎのパターンは説明として、司会者モンティかならず「あたり」の箱を開かないということが自明です。なので、その逆を選ぶというロジックにしたわけですが、何回か実行してみて大体2/3の割合で「あたり」がでるようです。
※プログラムがまちがっていなかったら。

まずは結果から
出力をひとつづつ追うとたしかに、わかってきます。
司会者モンティは、「かならず」あたりではない「やぎ」の箱を開きます!!

各 10回 試行します
[ヤギ] [ヤギ] [あたり]
あなたが選んだ箱は:[ヤギ]
[ヤギ] [ヤギ] [あたり]
あなたが選んだ箱は:[ヤギ]
[ヤギ] [あたり] [ヤギ]
あなたが選んだ箱は:[あたり]
[ヤギ] [ヤギ] [あたり]
あなたが選んだ箱は:[ヤギ]
[ヤギ] [あたり] [ヤギ]
あなたが選んだ箱は:[ヤギ]
[ヤギ] [あたり] [ヤギ]
あなたが選んだ箱は:[ヤギ]
[ヤギ] [あたり] [ヤギ]
あなたが選んだ箱は:[あたり]
[ヤギ] [あたり] [ヤギ]
あなたが選んだ箱は:[ヤギ]
[あたり] [ヤギ] [ヤギ]
あなたが選んだ箱は:[あたり]
[あたり] [ヤギ] [ヤギ]
あなたが選んだ箱は:[ヤギ]

[あたり] [ヤギ] [ヤギ]
あなたが最初に選んだ箱は:[ヤギ]
残りの箱:[あたり] [ヤギ]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[あたり]
[ヤギ] [あたり] [ヤギ]
あなたが最初に選んだ箱は:[あたり]
残りの箱:[ヤギ] [ヤギ]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[ヤギ]
[あたり] [ヤギ] [ヤギ]
あなたが最初に選んだ箱は:[あたり]
残りの箱:[ヤギ] [ヤギ]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[ヤギ]
[ヤギ] [あたり] [ヤギ]
あなたが最初に選んだ箱は:[ヤギ]
残りの箱:[あたり] [ヤギ]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[あたり]
[あたり] [ヤギ] [ヤギ]
あなたが最初に選んだ箱は:[ヤギ]
残りの箱:[あたり] [ヤギ]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[あたり]
[ヤギ] [ヤギ] [あたり]
あなたが最初に選んだ箱は:[ヤギ]
残りの箱:[ヤギ] [あたり]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[あたり]
[あたり] [ヤギ] [ヤギ]
あなたが最初に選んだ箱は:[あたり]
残りの箱:[ヤギ] [ヤギ]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[ヤギ]
[ヤギ] [あたり] [ヤギ]
あなたが最初に選んだ箱は:[ヤギ]
残りの箱:[ヤギ] [あたり]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[あたり]
[あたり] [ヤギ] [ヤギ]
あなたが最初に選んだ箱は:[ヤギ]
残りの箱:[あたり] [ヤギ]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[あたり]
[あたり] [ヤギ] [ヤギ]
あなたが最初に選んだ箱は:[あたり]
残りの箱:[ヤギ] [ヤギ]
モンテぃは箱を開いた:[ヤギ] あなたが選んだ箱は:[ヤギ]

*** はじめの選択から変更しない場合
当たった回数: 3/10
*** はじめの選択から変更する場合
当たった回数: 6/10



この結果を選んだの恣意的になのだけど、大体こんな結果になります。
最初に選んだ箱を変えない場合は、「あたり」が3/10という結果に。

モンティの開いた箱の逆を選ぶ場合は、6/10という結果に。

以下作成したコード
Javaです。
import java.util.Random;

public class A_MontyHallproblem {

final static String BINGO = "あたり";

public static void main(String[] args) {
int trycount = 10;
int c1, c2 = 0;
System.out.println("各 " + trycount + "回 試行します");

{
c2 = b(trycount, false);

}
System.out.println();
{
c1 = b(trycount, true);

}

System.out.println();
System.out.println("*** はじめの選択から変更しない場合");
System.out.println("当たった回数: " + c2 + "/" + trycount);
System.out.println("*** はじめの選択から変更する場合");
System.out.println("当たった回数: " + c1 + "/" + trycount);
}

static int b(int tryCount, boolean rechoice) {
int c = 0;
for (int i = 0; i < tryCount; i++) {
boolean b = a(rechoice);
// System.out.println();
if (b)
c++;
}

return c;
}

static boolean a(boolean rechoice) {
String[] box = box();
for (String s : box) {
System.out.print("[" + s + "] ");
}
System.out.println();

int yourFirstChoice = yourChoice(3);

//
if (rechoice) {

String[] box2 = new String[2];
int pos = 0;
for (int i = 0; i < 3; i++) {
if (yourFirstChoice != i) {
box2[pos++] = box[i];
}
}
System.out.println(" あなたが最初に選んだ箱は:[" + box[yourFirstChoice] + "]");
// 残りの箱
System.out.print(" 残りの箱:");
for (String s : box2) {
System.out.print("[" + s + "] ");
}
System.out.println();
// モンテぃは必ず当たりじゃないものを選ぶので、その逆をあなたは選択するとします。
if (!box2[0].equals(BINGO)) {
System.out.println(" モンテぃは箱を開いた:[" + box2[0]
+ "] あなたが選んだ箱は:[" + box2[1] + "]");
return box2[1].equals(BINGO);
}
System.out.println(" モンテぃは箱を開いた:[" + box2[1] + "] あなたが選んだ箱は:["
+ box2[0] + "]");
return box2[0].equals(BINGO);
} else {
System.out.println(" あなたが選んだ箱は:[" + box[yourFirstChoice] + "]");
if (box[yourFirstChoice].equals(BINGO)) {
return true;
}
}

return false;
}

static int yourChoice(int c) {
Random random = new Random();
return random.nextInt(c);
}

static String[] box() {
String[] box = { "ヤギ", "ヤギ", "ヤギ" };
Random random = new Random();
int i = random.nextInt(3);
box[i] = BINGO;
return box;
}
}




2009-11-23

TBitmapを使ってみる。その一


はじめてのdelphiです。
Delphi2010を使ってます。
勉強がてらに使ってみます。
今後、Delphiはwindows上での作業のヘルパーアプリ作成用にメインで使っていこうかなと考えてます。

お題はアスキーアートです。
どういうことをしたいかといいますと、入力された文字列をアスキーアート風に表示したいというわけです。

まず文字列処理がわからない。
制御文の書き方がわからない。
といろいろわからないことだらけですが、ジョジョになれていきたいところです。



いくつかわかったこと。

  • VisualBaisicであったDebug.Printみたいなものが、OutputDebugStringとなるみたい。
  • 制御文字を#13とかを文字列と+で連結できる。
  • TBitmapを使えばグラフィック操作ができて、ファイルとかに簡単に入出力できる。
  • ポインタとかフリーとかメモリを扱ってることを意識しないといけない。
  • Bitmap.Monochrome=Trueではまった。Bitmap.PixelFormat := pf8bit;でよいかも。
  • Delphi2010にコード整形が撞いている
  • TBitmap が DDB を保持しているときは ScanLine プロパティは正しく扱えない!?
  • TMemoで改行を入れたあげたい場合はCR+LFで。
  • 自作関数からの戻り値はResultという暗黙の変数に入れてあげること。

参考リンク
TCanvas オブジェクト
2. TBitmap.Scanline を使う際の注意
Delphi では「改行コード」などの制御文字や英字など「アスキーコード表にある文字」を「#」を使って手軽に指定できます。

以下コード
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
TextIn: TEdit;
Button1: TButton;
TextOut: TMemo;
procedure Button1Click(Sender: TObject);

private
{ Private 宣言 }
public
{ Public 宣言 }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

//
function ScaneLine(Bitmap: TBitmap): String;
var
x, y: Integer;
P: PByteArray;
S: String;
begin
for y := 0 to Bitmap.Height - 1 do
begin
P := Bitmap.ScanLine[y];
for x := 0 to Bitmap.Width - 1 do
begin
if 0 = P[x] then
begin
S := S + '1';
end
else
begin
S := S + ' ';
end;
S := S + ' ';
end;
S := S + #13 + #10;
end;
Result := S;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
S: String;
Bitmap: TBitmap;
begin
Bitmap := TBitmap.Create;
Bitmap.PixelFormat := pf8bit;

Bitmap.Width := 80;
Bitmap.Height := 30;
// Bitmap.Monochrome := True;
S := TextIn.Text;
OutputDebugStringW(PChar(S));
TextOut.Text := S;

Bitmap.Canvas.Font.Height := 30;
Bitmap.Canvas.TextOut(0, 0, S);

TextOut.Text := ScaneLine(Bitmap);
Bitmap.SaveToFile('c:\tmp\a.bmp');
Bitmap.Free;

end;

end.




2009-11-18

呑む - PixelGrabber使ってます。


__________________________________________________
__________________________________________________
________________@@________________________________
____________@@@@@_@__________@____________________
__@@@@@@@@@@_________________@____________________
__________@__________________@___@__@@____________
__________@_____________@@@@@@@@@@____@___________
_________@______________@@@@@@@________@__________
_@@@@@@@@@@@@@@@@@@@@________@__________@_________
_@@@@@@@@@@@@@@@@@@@@________@___________@@_______
________@___@______________@@@___________@________
_______@_____@____________@@@@____________________
_______@______@__________@___@____________________
______@________@@_______@@___@@___________________
____@@@@@@@@@@@@@@_______@___@________@@__________
___@@@@@@@@@@@@@@_@______@@@@__________@__________
_@@__@@________@@__@@@____@_@__________@__________
_@___@@________@@___________@__________@__________
_____@@________@@__________@@__________@@_________
_____@@________@@___________@_________@@__________
_____@@@@@@@@@@@@___________@@@@@@@@@@@___________
_____@@@@@@@@@@@@_____________@@@@@@______________
_____@@________@@_________________________________


Javaです。
PixelGrabber使ってます。

うーん。だめだめですね。
Orz...
失敗ですね。
アスキーアートどうつくるのかしら...

ブラウザで表示する際に、<pre style="font-family:MS ゴシック;"></pre>で囲むようにした。


import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;

public class Aascii {

public static void main(String[] args) throws InterruptedException {
a();
}

static void a() throws InterruptedException {
int w = 50;
int h = 23;
BufferedImage image = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.setFont(new Font("", Font.PLAIN, 22));
g2d.drawString("呑む", 0, 21);
g2d.dispose();
PixelGrabber grabber = new PixelGrabber(image, 0, 0, w, h, false);
// System.out.println(grabber.grabPixels());
grabber.grabPixels();
Object o = grabber.getPixels();
int[] is = (int[]) o;
int pos = 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (is[pos++] != 0) {
System.out.print("@");
} else {
System.out.print("_");
}

}
System.out.println();
}
}
}




2009-11-03

[perl]サブルーチンの引数


perlです。
サブルーチンの引数の指定の仕方。
この書き方すっきりしてるなと思った次第。
ちなみにこの方法だと引数のもとの値の上書きとか、副作用がないようですね。

#!/usr/bin/perl

sub func {
my ($a, $b, $c) = @_;
print "$a $b $c\n";
}

func("ok1", "ok2", "ok3");


参考




 

プログラマの本棚