人生を一日とすると今日は何時か.

Sonyの採用企画でプログラミングコンテストをやっているので解きました.

  • あなたの一生を24時間にたとえると今日は何時何分何秒ですか?
    • ただしあなたはあなたの誕生日(a年b月c日)の0時ちょうどに生まれてn歳まで生きる(n歳のときは生きていてn+1歳にはなれない)とし、bとcは一般的な月日の範囲とします。
import java.text.SimpleDateFormat;
import java.util.Date;


public class ClockOfLife {

	public static void main(String[] args) {
		int year = 1988;
		int month = 1;
		int day = 28;
		int life = 80;
		ClockOfLife clockOfLife = new ClockOfLife(year,month,day,life); 
		System.out.println(clockOfLife.getAnswer());
	}

	private Day birthDay;
	private Day deathDay;
	
	public ClockOfLife(int year,int month,int day,int life){
		this.birthDay = new Day(year,month,day);
		this.deathDay = new Day(year+life+1,month,day);		
	}

	public void setBirthDay(int year,int month,int day){
		this.birthDay = new Day(year,month,day);
	}

	public void setLife(int life){
		this.deathDay = new Day(this.birthDay.year+life+1,this.birthDay.month,this.birthDay.day);
	}
	public void setDeathDat(int year,int month,int day){
		this.deathDay = new Day(year,month,day);
	}
	
	public String getAnswer(){
		return this.getTimeFromMinutes(this.getNowSeconds());
	}
	private String getTimeFromMinutes(int minutes){
		int minute = minutes%60;
		int second = ((minutes - minute)%3600/60);
		int hour = (minutes - minute - second*60)/3600;
		return hour+"時"+second+"分"+minute+"秒";
	}
	
	private int getNowSeconds(){
		int oneDayMinutes = 60*60*24;
		Date date = new Date();
		SimpleDateFormat dayFormat = new SimpleDateFormat("dd");
		SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
		SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
	    
		int nowDay = Integer.parseInt(dayFormat.format(date));
		int nowMonth = Integer.parseInt(monthFormat.format(date));
		int nowYear = Integer.parseInt(yearFormat.format(date));
		
		Day today = new Day(nowYear,nowMonth,nowDay);
		int nowLostDay = this.getDays(this.birthDay,today);
		int lifeAllDay = this.getDays(this.birthDay,this.deathDay);
		return oneDayMinutes*nowLostDay/lifeAllDay;
	}
	private int getDays(Day fromDay,Day toDay){
		int lifeAllDay = 0;
		for(int i=fromDay.year;i<toDay.year+1;i++){
			lifeAllDay += 365;
			if( this.isUrudoshi(i) ){
				lifeAllDay++;
			}
		}
		lifeAllDay -= this.getLostDayTheYear(fromDay);
		lifeAllDay -= this.getLostDayTheYear(new Day(toDay.year,12,32)) - this.getLostDayTheYear(toDay);
		return lifeAllDay;
	}
	private int getLostDayTheYear(Day day){
		int days = 0;
		for(int i=1;i<day.month;i++){
			if ( i == 2){
				if( this.isUrudoshi(day.year) ){
					days += 29;
				}else{
					days += 28;
				}
			}else if( i == 4 || i == 6 || i == 9 || i == 11 ){
				days += 30;
			}else{
				days += 31;
			}
		}
		days += day.day - 1;
		return days;
	}
	private boolean isUrudoshi(int year){
		if( year%4 != 0 ){
			return false;
		}else if( year%100 != 0 ){
			return true;
		}else if( year%400 == 0 ){
			return true;
		}else{
			return false;
		}
	}
}
class Day {
	public int year;
	public int month;
	public int day;
	public Day(int year,int month,int day){
		this.year = year;
		this.month = month;
		this.day = day;
	}
}

[HTML5] audio, video タグのmediagroupタグが効かない.

HTML5で音声,動画を手軽に再生出来るようになったのですが,

複数の動画,音声を同期して再生しようとしたところ,
mediagroupタグではまりました.

mediagroupタグを使おうと思ったら,
(現時点では?)
gitHub - mediagroup https://github.com/rwldrn/mediagroup.js/
を使わないといけないっぽいです.

このjsを読み込めば使えるようになるのですが,
いろいろ複雑な仕様があります.

  • controls属性を指定したプレーヤが同じグループのプレーヤの制御権限をもつ.
  • グループ内の複数のプレーヤにcontrols属性を書いては行けない.

複数指定すると一番始めのコントローラ以外はグループから追い出されます.

  • コントローラ以外のグループ内プレーヤは,音が出ない.

しかも,コントローラを途中で別のプレーヤに変えて音を出そうとするとおかしくなる.

なので1つのグループ内で音を出せるプレーヤは1つだけということですね.

[Java] DataOutputStreamクラスの仕様がおかしい.

Socket通信の際のデータをやりとりには,

出力 : DataOutputStreamクラス
入力 : InputStreamクラス

を使います.

入力に関しては,
InputStreamクラスを基に,

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

みたいにして使えばいいです.

出力に関しては,
DataOutputStreamクラスを直接使うのですが,
このクラスの書き込みメソッドがいくつかあって,
writeByte(Byte byte)
writeBytes(String string)
...

などがあるのですが、
普通にStringを送る事しか考えなかった場合,
writeBytes(String string)に飛びつく訳です.

しかし,この関数のドキュメントをよく読むと

文字列を基本となる出力ストリームに一連のバイトとして書き込みます。文字列中の各文字型データは順番に書き込まれ、このとき上位 8 ビットは無視されます。

大事なのは最後です.

このとき上位 8 ビットは無視されます。

謎です..
日本人の敵としか思えない.


なので,
日本語を送るときは,

writeBytes(String string)

ではなく,

Byte[] bytes = string.getBytes();
for (int i=0;i<bytes.length;i++){
    writeByte(bytes[i]);
}

を使わないと文字化けしてしまいます.

[Perl]複数カラムのあるデータのソート

ソートは昇順として実装してあります.
Perlのバージョンが5.8.6以降でないとsort関数が安定じゃないのでこれより新しいものにして下さい.
区切られてる文字によって
16行目

    my @strlist = split(/ /, $_);

を変えて下さい.

use strict;
use warnings;

my $input_file_path = shift;
my $output_file_path = shift;

my @sort_key = @ARGV;
my $sort_key_number = @sort_key;
my @sort_target;

open my $fh, "< ".$input_file_path;
my $index = 0;
while(<$fh>){
    chomp($_);
    #space一個でカラムが区切られてるとする.
    my @strlist = split(/ /, $_);
    my $hash;
    foreach my $key(@sort_key){
        $hash->{$key} = $strlist[$key];
    }
    $hash->{"index"} = $index;
    push(@sort_target, $hash);
    $index++;
}
close($fh);
#sort
my @sorted = @sort_target;

foreach my $key(reverse @sort_key){
    @sorted = sort { $a->{$key} <=> $b->{$key} } @sorted;
}
open my $out, ">".$output_file_path;
foreach my $hash_tmp (@sorted){
    my $index_number = $hash_tmp->{"index"};
    my $i = 0;
    open my $in, "< ".$input_file_path;
    while(<$in>){
        if($i eq $index_number){
            print $out $_;
            last;
        }else{
            $i++;
        }
    }
    close($in)
}
close($out);


使い方は,

$perl MargeSort.pl 入力ファイル 出力ファイル ソート順位が高い順に列数を指定(0から始まる)
例)
$perl MargeSort.pl test2.dat hoge.txt 0 1
      • 追記

id:hidekiyに指摘をもらったので訂正します.
chompの部分とか致命的ですね.

[Mac] MacBook airでキーボードのカーソルの移動速度が遅い.

Macbook Proを触ってた人なら感じると思いますが,
airのキーカーソルの移動速度ってやたら遅いです.

一番先頭に移動するならCtrl + aで行けますが,
真ん中くらいに移動するときのストレスはやばい.

いろいろ調べたら,
KeyRemac4Macbook
でスピードを変更出来るそうです.

「Key Repeat」タブの

Initial Wait : 100
Wait : 28

で丁度良さそうです.

[Java][Database] Javaでwebサービス - JavaDB

Javaには,JavaDBという組み込みのSQLがあるのです.
詳しくは,

データベースを触る部分のラッパーを書きました.
必要なライブラリは,
derby.jar と derbyclient.jar

ただこのコードはSQLサーバを立ち上げて複数クライアントからの通信を受け付けるって感じではないので,複数のインスタンスをつくることは出来ません.ご了承を.

というかそういう使い方をするのならMySQLの方が良いと思う.

Database.java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Database {
    private Connection connection;
    private Statement statement;
    private String databaseName;
    public Database(String databaseName){
        this.databaseName = databaseName;
        this.connect();
    }
    private void connect(){
        this.connection = null;
        this.statement = null;
        try {
            this.connection = DriverManager.getConnection(
                    "jdbc:derby:" + this.databaseName + ";create=true"
            );
            try {
                this.statement = this.connection.createStatement();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } catch(SQLException se) {
            for (SQLException e = se; e != null; e = e.getNextException()) {
                System.err.printf("%s: %s%n", e.getSQLState(), e.getMessage());
            }
        }
    }
    public boolean checkTableExist(String table){
        String query = "SELECT * FROM SYS.SYSTABLES WHERE TABLENAME='" + table + "'";
        ResultSet rs = this.throwQueryGet(query);
        int i = 0;
        try {
            while(rs.next()){
                i++;
            }
            rs.close();
        } catch (SQLException e) {
        }
        if( i > 0){
            return true;
        }else{
            return false;
        }
    }

    public void insert(String table,HashMap<String,String> values){
        if(this.checkTableExist(table)){
            Set<Map.Entry<String, String>> set = values.entrySet();
            Iterator<Map.Entry<String, String>> it = set.iterator();
            HashMap<String,Integer> tableType = this.getTableType(table);

            String query = "INSERT INTO " + table;
            String key = "(";
            String data = "(";
            while(it.hasNext()){
                Map.Entry<String, String> entry = it.next();
                String nowKey = entry.getKey();
                String nowData = entry.getValue();
                if(tableType.get(nowKey) == java.sql.Types.VARCHAR || tableType.get(nowKey) == java.sql.Types.CHAR ){
                    data += "'" + nowData + "',";
                }else{
                    data += nowData + ",";
                }
                key += nowKey + ",";
            }
            key = key.substring(0,key.length()-1);
            data = data.substring(0,data.length()-1);
            key += ")";
            data += ")";
            query += key + " VALUES "+ data;
            this.throwQuery(query);
        }else{
            System.out.println(table+" is not exist.");
        }
    }

    public void createTable(String name,ArrayList<String> info){
        if(!this.checkTableExist(name)){
            String query = "CREATE TABLE "+ name + " (";
            for(int i=0;i<info.size();i++){
                query += info.get(i) + ",";
            }
            query = query.substring(0,query.length()-1);
            query += ")";
            this.throwQuery(query);
        }else{
            System.out.println(name+" is exist.");
        }
    }

    public HashMap<String,Integer> getTableType(String table){
        HashMap<String,Integer> type = new HashMap<String,Integer>();
        ResultSet rs = this.throwQueryGet("SELECT * FROM "+table);
        try {
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();
            for(int i=1;i<columnCount+1;i++){
                type.put(metaData.getColumnName(i),metaData.getColumnType(i));
            }
            return type;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public ArrayList<HashMap<String,Object>> select(ArrayList<String> info){
        ArrayList<HashMap<String,Object>> array = new ArrayList<HashMap<String,Object>>();
        String query = "SELECT ";
        for(int i=0;i<info.size();i++){
            query += info.get(i) + " ";
        }
        query = query.substring(0,query.length()-1);
        ResultSet rs = this.throwQueryGet(query);
        try {
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();
            ArrayList<String> columnNameList = new ArrayList<String>();
            for(int i=1;i<columnCount+1;i++){
                columnNameList.add(metaData.getColumnName(i));
            }
            while (rs.next()) {
                HashMap<String,Object> dataMap = new HashMap<String,Object>();
                for(int i=0;i<columnCount;i++){
                    String columnName = columnNameList.get(i);
                    dataMap.put(columnName,rs.getObject(columnName));
                }
                array.add(dataMap);
            }
            rs.close();
            return array;
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
        return null;
    }

    public void dumpData(ArrayList<HashMap<String,Object>> data){
        System.out.println("----DataDumper----");
        for(int i=0;i<data.size();i++){
            Iterator it = data.get(i).keySet().iterator();
            while (it.hasNext()){
                Object o = it.next();
                System.out.println(o + " = " + data.get(i).get(o));
            }
            System.out.println();
        }
        System.out.println("------------------");
    }

    private void throwQuery(String query){
        System.out.println(query);
        try {
            this.statement.execute(query);
        } catch (SQLException se) {
            for (SQLException e = se; e != null; e = e.getNextException()) {
                System.err.printf("%s: %s%n", e.getSQLState(), e.getMessage());
            }
        }
    }

    private ResultSet throwQueryGet(String query){
        System.out.println(query);
        try {
            return this.statement.executeQuery(query);
        } catch (SQLException se) {
            for (SQLException e = se; e != null; e = e.getNextException()) {
                System.err.printf("%s: %s%n", e.getSQLState(), e.getMessage());
            }
            return null;
        }
    }

    public void finalize(){
        try {
            this.statement.close();
            this.connection.close();
            DriverManager.getConnection("jdbc:derby:"+this.databaseName + ";shutdown=true");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

[Java][Socket] Javaでwebサービス - Socket通信

Java以外のプログラムと通信する場合,Socket通信なるものを使います.


今回はJavaに閉じたお話で,Socket通信について.


Socket通信についてはググったらいろいろ出てきます.google is your friend です.


個人的に,JavaでのSocket通信で大事かなと思った点を書きます.

  • サーバー側がポートを開いてクライアントはサーバーのホスト名とポート番号を指定してつなぎにいく.

ソケット通信の流れは以下になります.
1.サーバーがソケットを作成

ServerSocket serverSocket = new ServerSocket(portNumber);

2.サーバーのソケットを受け入れ体制に

Socket socketOfServer = serverSocket.accept();

3.クライアントがソケットを作成

Socket socketOfClient = new Socket(hostName,portNumber);

4クライアントのソケットをサーバーのソケットとつなげる.(通信開始)

socketOfClient.connect();

5.クライアントからデータを送る
5.1.データをストリームに書き込む

ObjectOutputStream clientOutputStream = new ObjectOutputStream(socketOfClient.getOutputStream());
clientOutputStream.writeObject(data);

5.2.書き込み終了

clientOutputStream.flush();

5.3.サーバーでデータを受け取る

ObjectInputStream serverInputStream =  new ObjectInputStream(socketOfServer.getInputStream());
Object data = serverInputStream.readObject();

6.サーバーからデータを送る
6.1.ストリームに書き込み

ObjectOutputStream serverOutputStream = new ObjectOutputStream(socketOfServer.getOutputStream());
serverOutputStream.writeObject(data);

6.2.書き込み終了

serverOutputStream.flush();

6.3.クライアントでデータを受け取る

ObjectInputStream clientInputStream =  new ObjectInputStream(socketOfServer.getInputStream());
Object data = clientInputStream.readObject();

7クライアントでソケットを閉じる

clientSocket.close();
  • クライアントでソケットを閉じるともう一度サーバー側もソケットを作り直さなければならない.(自動的にsocket.close()がよばれる?)
  • 同じサーバーソケットに同時に複数のソケットをつなげることができる.
  • serverSocket.accept();でそのスレッドはstopする.

clientからconnectされれば動き出す.

  • clientSocket.connect();でそのスレッドはstopする.

serverSocketと繋がれば動き出す.

  • つまり,順番的にaccept()とconnect()どちらを先に実行しても大丈夫.

以下サンプルコード
ソケットの部分をサーバーとクライアントで別々にラップしてます.
クライアントを別スレッドで立ててクライアントから投げた値を素因数分解して,その値を返すプログラムです.

Main.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Main {

    public static void main(String[] args) {
        int portNumber = 50000;
        String hostName = "localhost";
        SocketServer server = new SocketServer(portNumber);
        ClientThread clientThread = new ClientThread(hostName, portNumber);
        Thread thread = new Thread(clientThread);
        thread.start();
        while(true){
            server.Accept();
            ObjectInputStream serverInputStream = server.getObjectInputStream();
            Integer data;
            try {
                data = (Integer)serverInputStream.readObject();
                ArrayList<Integer> array = new ArrayList<Integer>();
                int factor = 2;
                while(data != 1){
                    if( data%factor == 0 ){
                        array.add(factor);
                        data = data/factor;
                    }else{
                        factor++;
                    }
                }
                ObjectOutputStream serverOutputStream = server.getObjectOutputStream();
                serverOutputStream.writeObject(array);
                serverOutputStream.flush();
            } catch (IOException e1) {
                e1.printStackTrace();
            } catch (ClassNotFoundException e1) {
                e1.printStackTrace();
            }
        }
    }
}

SocketClient.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketClient {
    private String hostName;
    private int portNumber;
    private Socket socket;

    public SocketClient(String hostName,int portNumber){
        this.hostName = hostName;
        this.portNumber = portNumber;
    }

    public Socket connect(){
        try {
            this.socket = new Socket(this.hostName,this.portNumber);
        } catch (UnknownHostException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return this.socket;
    }

    public void close(){
        try {
            this.socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public ObjectInputStream getObjectInputStream(){
        try {
            return new ObjectInputStream(this.socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public ObjectOutputStream getObjectOutputStream(){
        try {
            return new ObjectOutputStream(this.socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void finalize(){
        try {
            this.socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

SocketServer.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServer {
    private int portNumber;
    private ServerSocket serverSocket;
    private Socket socket;

    public SocketServer(int portNumber){
        this.portNumber = portNumber;
        try {
            this.serverSocket = new ServerSocket(this.portNumber);
        } catch (IOException e) {
            System.out.println("Failed to Create ServerSocket..");
            e.printStackTrace();
        }
    }

    public void Accept(){
        try {
            this.socket = this.serverSocket.accept();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public ObjectInputStream getObjectInputStream(){
        try {
            return new ObjectInputStream(this.socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public ObjectOutputStream getObjectOutputStream(){
        try {
            return new ObjectOutputStream(this.socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public ServerSocket getServerSocket(){
        return serverSocket;
    }

    public void finalize(){
    }
}

ClientThread.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ClientThread implements Runnable{
    private String hostName;
    private int portNumber;

    public ClientThread(String hostName,int portNumber){
        this.hostName = hostName;
        this.portNumber = portNumber;
    }
    @Override
    public void run() {
        for(int i=2;i<10;i++){
            SocketClient client = new SocketClient(this.hostName, this.portNumber);
            client.connect();
            ObjectOutputStream clientOutputStream = client.getObjectOutputStream();
            Integer data = new Integer(i);
            try {
                System.out.println("Input : "+ data);
                clientOutputStream.writeObject(data);
                clientOutputStream.flush();

                ObjectInputStream clientInputStream = client.getObjectInputStream();
                ArrayList<Integer> getData = (ArrayList<Integer>)clientInputStream.readObject();
                String out = new String();
                for(int j=0;j<getData.size();j++){
                    out += " " + getData.get(j);
                }
                System.out.println("Get :" + out);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            client.close();
        }
    }
}