にたまごほうれん草アーカイブ

はてなダイアリーで書いてた「にたまごほうれん草」という日記のアーカイブです。現在は「にたまごほうれん草ブログ」を運営中です。

Project Eulerを始めてみる

gomi-boxさんのところで、Project Eulerをやっていて興味を惹かれたので、私も挑戦してみることにします。
最近プログラムを書いていない鬱憤晴らしと勉強を兼ねてC言語で。

まずは環境作り

問題を解くのに集中できるよう、解答プログラムのテンプレートを用意して、数式処理以外のところを自動生成するRubyスクリプトを作りました。
問題番号を指定するとProject Eulerの公式サイトから問題文などを取得してコードの先頭にコメントで張り付けてます。

$ ./makeprog.rb problem 001 .c

とすると、template.txtに書いてあるテンプレートに問題文を当てはめてファイルを生成します。スクリプトの引数は、プレフィクス・問題番号・サフィックスの順に指定します。上記の例ではproblem003.cが作成されます。

makeprog.rb

要Mechanizeです。プレフィクスとサフィックス固定でよければ、引数から読み込むところを定数文字列にすればOK。

#! /usr/bin/env ruby
require 'rubygems'
require 'mechanize'

prefix = ARGV.shift
id     = ARGV.shift
suffix = ARGV.shift

exit if id.nil?

agent = WWW::Mechanize.new

url = "http://projecteuler.net/index.php?section=problems&id=#{id}"

content = agent.get(url)
title = content.search('//title').first.inner_html
text = content.search('//div[@class="problem_content"]').first.inner_html.
  gsub(/<p(.*?)>/, '').gsub(/<\/p>/, "\n").gsub(/\r/,'')

puts title
puts text
puts url

id = sprintf("%03d", id.to_i)

template = open("template.txt").read
File.open("#{prefix + id + suffix}", "wb") {|fout|
  ['title', 'text', 'url', 'id'].each {|rep|
    eval("template.gsub!(/%%#{rep}%%/, #{rep})")
  }
  fout.write(template)
}

template.txt

私が作ったC言語用のテンプレートです。%%title%%->タイトル、%%text%%->問題文、%%url%%->問題文のURL、%%id%%->問題番号という置換です。

/**
 * %%title%%
 * %%text%%
 * %%url%%
 */
#include <stdio.h>

void problem%%id%%()
{
    int ans;

    /* solve this problem here */

    printf("%s: answer = %d\n", __FUNCTION__, ans);
}


int main(int argc, char* argv[]) 
{
    problem%%id%%();
    return 0;
}

Makefile

ついでなのでMakefileも晒しておきます。

CC = gcc
DEFINE=
INCLUDE=
CFLAGS=-g -Wall
LDFLAGS=-lm

TARGET = $(patsubst %.c, %, $(wildcard problem*.c))

.PHONY: all
all: $(TARGET)

%: %.c
	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

clean:
	rm -f $(TARGET) *.o *~