Amazon Ads

2015年6月24日 星期三

【筆記】用Java做蛇與樓梯(snakes and ladders)遊戲的簡單範例

今天在書上看到一個蛇與樓梯的程式,其規則大致如下:

  1. 擲骰子來決定要走的步數。
  2. 從數字1開始走到最大數字(如下圖中的25)。
  3. 若走到梯子下,就可以延著梯子爬上去(前進)。
  4. 若走到蛇頭,就要延著蛇身滑下去(倒退)。


其程式碼如下:
package idv.jk.fun;

public class SnakesAndLadders
{
    private static final int finalSquare = 25;

    public static void main(String[] args)
    {
        int[] board = new int[finalSquare + 1];

        for(int i = 0; i <= finalSquare; i++)
        {
            board[i] = 0;
        }

        //定義走到的格子要上樓梯或滑下蛇後,要前進或後退幾格
        board[3] = +8;
        board[6] = +11;
        board[9] = +9;
        board[10] = +2;

        board[14] = -10;
        board[19] = -11;
        board[22] = -2;
        board[24] = -8;


        int diceNumber = 0;//擲出的點數

        int step = 0; //走到第幾格

        while(step < finalSquare)
        {
            //擲骰子
            diceNumber = (int)(Math.random() * 6 + 1);
            System.out.print("擲出的點數: " + diceNumber + ", ");
            step += diceNumber;

            if(step < board.length)
            {
                if(board[step] > 0)
                {
                    System.out.print("上樓梯, 爬上 " + board[step] + " 格, ");
                }
                else if(board[step] < 0)
                {
                    System.out.print("下蛇身, 滑下 " + board[step] + " 格, ");
                }
                step += board[step];
            }
            System.out.println("前進到第 " + step + " 格");
        }
        System.out.println("結束");
    }
}
執行結果為:
擲出的點數: 3, 上樓梯, 爬上 8 格, 前進到第 11 格
擲出的點數: 3, 下蛇身, 滑下 -10 格, 前進到第 4 格
擲出的點數: 3, 前進到第 7 格
擲出的點數: 5, 前進到第 12 格
擲出的點數: 1, 前進到第 13 格
擲出的點數: 1, 下蛇身, 滑下 -10 格, 前進到第 4 格
擲出的點數: 4, 前進到第 8 格
擲出的點數: 4, 前進到第 12 格
擲出的點數: 6, 前進到第 18 格
擲出的點數: 6, 下蛇身, 滑下 -8 格, 前進到第 16 格
擲出的點數: 4, 前進到第 20 格
擲出的點數: 1, 前進到第 21 格
擲出的點數: 4, 前進到第 25 格
結束

2015年6月9日 星期二

【筆記】在Ubuntu 14.04中,用python來連線並查詢MySQL中的資料

先到這裡下載mysql-connector-python_2.0.4-1debian7.6_all.deb
wget http://dev.mysql.com/get/Downloads/Connector-Python/mysql-connector-python_2.0.4-1debian7.6_all.deb
並將其安裝:
sudo dpkg -i mysql-connector-python_2.0.4-1debian7.6_all.deb
安裝完成後,就開始來寫程式吧!這裡將程式存成mysql_query.py
#!/usr/bin/python
import mysql.connector
cnx = mysql.connector.connect(user='cbuser', password='cbpass',
                              host='127.0.0.1',
                              database='cookbook')

cursor = cnx.cursor();
query = "select a, b from test"
cursor.execute(query)

for(a, b) in cursor:
        print("column a is {}, column b is {}".
                format(a, b))

cursor.close()
cnx.close()
test這個資料表中的資料如下:
+---+------+
| a | b    |
+---+------+
| 1 | abc  |
| 2 | xyz  |
+---+------+
最後執行程式:
python mysql_query.py 
執行結果為:
column a is 1, column b is abc
column a is 2, column b is xyz

2015年6月3日 星期三

【筆記】使用MapReduce來替換字串(replace string)的簡單程式

拜歐先把要替換的檔案上傳到HDFS中。

上傳完成後,使用下列指令檢視其內容:
hdfs dfs -cat /user/javakid/replace/replace.txt
輸入的檔案為replace.txt,其內容如下:
foo1234foo567foo890foo123foo
foo1234foo567foo890foo123foo
foo1234foo567foo890foo123foo
foo1234foo567foo890foo123foo
foo1234foo567foo890foo123foo
foo1234foo567foo890foo123foo
foo1234foo567foo890foo123foo
foo1234foo567foo890foo123foo
foo1234foo567foo890foo123foo
foo1234foo567foo890foo123foo
再來開始寫程式,拜歐是用Intellij IDEA來撰寫程式,在專案設定中,將編譯的輸出目錄(compile output path)設定為/home/javakid/study/hadoop/classpath

第一個要寫的是 mapper
package idv.jk.study.hadoop.myself;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

/**
 * Created by javakid on 2015/6/3.
 */
public class StringReplaceMapper
        extends Mapper<LongWritable, Text, NullWritable, Text>
{
    private static final String TARGET = "foo";
    private static final String REPLACEMENT = "bar";

    @Override
    protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException
    {
        String line = value.toString();

        if(line.indexOf(TARGET) >= 0)
        {
            context.write(NullWritable.get(),
                            new Text(line.replaceAll(TARGET, REPLACEMENT)));
        }
    }
}
mapper的輸出,拜歐要的只是替換後的每一行字串,這些值的key是什麼,並不重要,所以在上列程式中的第27行,用NullWritable來做為輸出的key。

再來要寫的是 reducer
package idv.jk.study.hadoop.myself;

import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/**
 * Created by javakid on 2015/6/3.
 */
public class StringReplaceReducer
        extends Reducer<NullWritable, Text, NullWritable, Text>
{
    @Override
    protected void reduce(NullWritable key, Iterable<Text> values, Context context)
            throws IOException, InterruptedException
    {
        for(Text text : values)
        {
            context.write(NullWritable.get(), text);
        }
    }
}
reducer中,拜歐要的也只是將已經在mapper替換好的字串輸出,在第21行一樣使用NullWritable來做為輸出的key。

最後是主程式:
package idv.jk.study.hadoop.myself;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

/**
 * Created by javakid on 2015/6/3.
 */
public class StringReplace
{
    public static void main(String[] argv)
            throws IOException, ClassNotFoundException, InterruptedException
    {
        if(argv.length != 2)
        {
            System.err.println("Usage: StringReplace <input path> <output path>");
            System.exit(-1);
        }

        Job job = new Job();
        job.setJarByClass(StringReplace.class);
        job.setJobName("String replacement");

        FileInputFormat.addInputPath(job, new Path(argv[0]));
        FileOutputFormat.setOutputPath(job, new Path(argv[1]));

        job.setMapperClass(StringReplaceMapper.class);
        job.setReducerClass(StringReplaceReducer.class);

        job.setOutputKeyClass(NullWritable.class);
        job.setOutputValueClass(Text.class);

        System.out.println(job.waitForCompletion(true) ? 0 : 1);
    }
}
上列setOutputKeyClasssetOutputValueClass這兩個方法控制reduce方法中輸出的型別,而且與reducer中產出的輸出中設定,兩者必須是相同的。

先將HADOOP_CLASSPATH設定好後,用hadoop指令來執行主程式:
export HADOOP_CLASSPATH=/home/javakid/study/hadoop/classpath
hadoop idv.jk.study.hadoop.myself.StringReplace \
/user/javakid/replace/replace.txt /user/javakid/replace/output
執行完成後,使用下列指令來確認結果:
hdfs dfs -cat /user/javakid/replace/output/part-r-00000
預期結果如下:
bar1234bar567bar890bar123bar
bar1234bar567bar890bar123bar
bar1234bar567bar890bar123bar
bar1234bar567bar890bar123bar
bar1234bar567bar890bar123bar
bar1234bar567bar890bar123bar
bar1234bar567bar890bar123bar
bar1234bar567bar890bar123bar
bar1234bar567bar890bar123bar
bar1234bar567bar890bar123bar
你可以在這裡找到原始碼。