Shuhei Kagawa

Python Challenge Lv. 6 - 7

Oct 11, 2009

システムアーキテクトの試験が来週末に迫っているのですが、またまたやってしまいました。現実逃避。 試験前ということを除けば、面白いし、自然と勉強になるので良いのですけどね。

Level 6

アドレスバーに何度も channel.zip と入れるも、ファイルがダウンロードされていることになかなか気付かず。気付いてファイルを解凍し、Level 4 的なプログラムで “Collect the comments.” に辿りつきましたが、意味がわかりません。 少しカンニングしてみると、ZIP ファイルは中身のファイル毎にコメントを付けられるのだとか。Python の zipfile モジュールで見られるらしいので、やってみました。

num = "90052"
z = zipfile.ZipFile("channel.zip")

while True:
  # Print file's comment
  print z.getinfo(num + ".txt").comment,
  # Get next nothing
  s = open(num + ".txt").read()
  m = pattern.match(s)
  if m:
    num = m.group(1)
  else:
    break

Python で改行なしの出力をするには print "foo", なんですね。 いつのまにか Python で解いてしまってますね・・・。

Level 7

from PIL import Image
image = Image.open("oxygen.png")
width = image.size[0]
data = list(image.getdata())

before = 0
message = ""
for x in range(width):
  tmp = data[x + width * 46][0]
  if tmp != before:
    message += "%c" % (tmp)
    before= tmp

print message

これで下記メッセージが表示されるのですが、この配列の意味がわかりません・・・。

smart guy, you made it. the next level is [105, 10, 16, 101, 103, 14, 105, 16, 121]ljljlimkljhdfdcdfa]_a

少しカンニングをして気がついたのですが、 if tmp != before: としているのがマズかったようです。これだと同じ文字が続く場合に無視されてしまいます。 気を取り直して以下。書き方も少し Python らしく(?)。 chr という関数があったんですね。

from PIL import Image
image = Image.open("oxygen.png")
width = image.size[0]
data = list(image.getdata())
message = []
i = 0
while True:
  color = data[i + width * 46]
  if color[0] == color[1] == color[2]:
    message.append(color[2])
    i += 7
  else:
    break

print "".join(map(chr, message))

出てきたメッセージから答えを出します。

print "".join(map(chr, [105, 110, 116, 101, 103, 114, 105, 116, 121]))

何だかカンニングしてばかりですね・・・。

Oct 11, 2009

Grasses.pde

パソコンの中にあったのを、絵作りのとこだけアップ。そういえば、何か作っていたのでした。 備忘のために。

int NUM;
float[] grasses;

void setup()
{
  size(495, 140);
  smooth();
  background(255);

  NUM = width;

  grasses = new float[NUM];
  for (int i = 0; i < NUM; i++)
  {
    grasses[i] = random(0, 1) * random(0.5, 1);
  }
  drawGrasses();
  save("grasses.png");
}

void drawGrasses()
{
  noFill();
  colorMode(HSB);
  for (int i = 0; i < NUM; i++)
  {
    stroke(random(50, 100), 200, 200);
    strokeWeight(width * 0.0015 * random(0.5, 1));

    int x = i * width / (NUM - 1);
    line(x,
         height,
         x + width * random(-0.1, 0.1) * random(-0.15, 0.15),
         height * (1.0 - grasses[i] * 0.3 - 0.2));
  }
}

Python Challenge Lv. 0 - 5

Oct 10, 2009

ふと mixi の Python コミュニティを覗いたら Python Challenge なるものを発見。 プログラムを書いて解いてゆくクイズです。面白そうなのでやってみました。 最近マイブームな Ruby で。

以下、ネタバレ注意です。

Level 0

2 ** 38

Level 1

cipher = "g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr'q ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj."
abc = ("a"[0] .. "z"[0]).to_a
cde = ("c"[0] .. "z"[0]).to_a + ["a"[0], "b"[0]]
dict = Hash[*abc.zip(cde).flatten]
cipher.bytes do |ch|
  ch = dict[ch] if dict.has_key?(ch)
  printf("%c", ch)
end

Level 2

ターミナルにコピペしたらおかしくなったので、一旦 mess_2.txt に保存。

File.open("mess_2.txt") do |f|
  while ch = f.getc
    printf("%c", ch) if ("a"[0] .. "z"[0]).include?(ch)
  end
end

ファイルの中身を 1 バイトずつ読み込んで、アルファベットだけ抜き出します。

Level 3

pattern = /[^A-Z][A-Z]{3}([a-z])[A-Z]{3}[^A-Z]/
File.open("mess_3.txt") do |f|
  p f.read.scan(pattern).to_s
end

Ruby でグローバルマッチしたい時って String#scan 使うしかないの?

Level 4

num = "12345"
require "net/http"
def get_nothing(num)
  return Net::HTTP.get URI.parse("http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=" + num)
end
400.times do
  content = get_nothing(num)
  m = /and the next nothing is ([0-9]+)/.match(content)
  p num
  p content
  if m != nil then
    num = m[1]
  else
    exit
  end
end

途中でひっかけがありますが・・・。そこは手作業で。

Level 5

意味がわからずカンニング。 Python Challenge level 5: “peak hell” | UnixWars Python の Pickle モジュールを使う問題だとか。知らんがな。

import urllib, pickle
uri = "http://www.pythonchallenge.com/pc/def/banner.p"
obj = pickle.load(urllib.urlopen(uri))
for line in obj:
  l = ""
  for pair in line:
    l += pair[0] * pair[1]
    print l

今日はここまで

続きはまた今度。