Language detail: PHP - 's unsolved challenges

文字列で+を表示する (Nested Flatten)
与えられた文字列で+のかたちを表示するプログラムをかいてください。
サンプル入力:
doukaku

サンプル出力:
       doukakud
       u      o
       k      u
       a      k
       k      a
       u      k
       o      u
doukakud      doukakud
u                    o
k                    u
a                    k
k                    a
u                    k
o                    u
dukakuod      dukakuod
       u      o
       k      u
       a      k
       k      a
       u      k
       o      u
       dukakuod
年賀はがきの当せん番号 (Nested Flatten)

年賀はがきの当せん番号について確認する方法をはがき(番号)の整理の仕方も含めて考えよ

箱詰めパズルの判定 (Nested Flatten)
以下の積み木のうち4つを、
重複を含めてランダムに選びます。
このとき、それらを4×4の箱に
詰められるかどうかを判定してください。

1.
■■■■

2.
■■
■■

3.
■■■
 ■

4.
■■■
■

5.
■■
 ■■

例えば、{ 1, 1, 1, 1 }, { 2, 2, 2, 2 } は箱につめることができますが、
{ 1, 2, 2, 3 } は箱につめることができません。

余力のある方は、以下の値を求めてみてください。
・箱につめることができる積み木の組み合わせの総数
・上記総数を、異なる詰め方の個数別にカウント
 (箱の回転・裏返しで一致するものは同一視します)
関数やメソッドのソースの平均行数 (Nested Flatten)

イントロスペクションおよびメトリックスのお題です。

アジャイル界隈などでは、あまり長くだらだらと書いてはいけない…と言われている 関数 and/or メソッド ですが、ならば実際のところ、洗練された既存のライブラリにおいて、関数 and/or メソッド は平均すると何行くらいで記述されているのか…といった情報を具体的に把握しておきたいと思ったことはありませんか?

そこで、みなさんイチオシの言語それ自身で書かれているライブラリを、それなりの規模になるように集めてきて、1)集めたライブラリ群内に定義されている全 関数 and/or メソッド の合計数(母集団の確認のため)、と 2)関数 or メソッドのソースの平均の行数、を求めるコードと、その結果を示してください。

なお、関数 and/or メソッドに帰属するものであれば、コメント行やアノテーションのたぐいも行数のカウントに含めてください(コードが必要以上に複雑にならない範囲で結構です)。また、関数内関数定義やメソッド内クラス定義(ひいてはその中でのメソッド定義)といった入れ子になったコードの行数をどう解釈するかの判断はお任せします。関数とメソッドが共存する言語では両者を区別してカウントする必要はありません(しても構いません)。平均値を求めるコードを、対象言語で記述することが技術的に困難な場合は、UNIX的なツールを組み合わせたり、IDEなどが提供するメトリックス機能を活用して算出した結果を示すのでもよいと思います。

このお題は、平均行数が 8.4 行(Squeak Smalltalk の組み込みライブラリ+αより、調査メソッド総数 4万)と、一般に簡潔さが美徳とされている Smalltalk からの挑戦(?)でもあります。

コレクションの実装 (Nested Flatten)

コレクションフレームワークに則ってコレクションクラスを実装して下さい.

具体的にどのようなコレクションを実装しても構いませんが,コレクションフレームワークで用意された基本的なメソッドは一通り呼べるようにして下さい. foreach系の構文があれば,それでも使えるとよいです.

例えば,Rubyであれば以下のようなコードで(mapを直接定義することなく)要素を列挙できる必要があるでしょう.

1
2
3
4
5
6
p MyCollection.new.map {|i| i }

# for でも使える
for i in MyCollection.new
  p i
end
居眠り床屋問題 (Nested Flatten)

並行処理のお題です。ある床屋の亭主は、客がいないときまって居眠りを始めます。床屋店内には三台の散髪兼順番待ち用の椅子があり、客は来店時に椅子に空きがあれば、いずれかに勝手に座って自分の番が来るのを待ち、散髪を終えてから店を出ます。空席が無ければそのまま何もせずに立ち去ります。居眠り中の亭主は、客の入店時に起こされると待ち客すべてをひとりずつ順に散髪しますが、誰もいなくなればまた居眠りを始めます。

この床屋店に16人の客が訪れた日のシミュレーションを行なうコードと、その結果(下に例として示したログ形式。「[スレッドのIDなど] イベント描写」の一覧と終了後の総括)を出力して示してください。なお、散髪には一人当たり100~400ミリ秒の時間(この範囲でランダムに変化)を要し、客は通常 0~200ミリ秒(同)の間隔で訪れます。ただし例外として9番目の客だけは前の客から1200ミリ秒程度の間隔(すなわち、最大三名の待ち客全員を散髪し終えるのに十分な時間)をあけて訪れるものとします。

実装に際し、実行時のデッドロックの回避はもちろんですが、そのほかにも、競合状態(席の空きを確認して座ろうとしたら、もう別の客が座っていた…というような事態)などの不整合も生じないよう配慮し、必要であればそのための対策を講じてください。たとえば来客の間隔が仮に0ミリ秒で固定の場合(つまり、客が一斉に来店した場合)でも、コードが正常に動作するかどうか試してみるのもよいかもしれません。

 

 

出力例:

[7302088] 床屋、眠る

[7012360] 来店 1

[7302088] 床屋、目覚める

[7302088] 散髪開始 1

[7012360] 来店 2

[7012360] 来店 3

[7302088] 散髪完了 1

[7302088] 散髪開始 2

[7012360] 来店 4

[7012360] 来店 5

[7012360] 満席で立ち去る 5

[7302088] 散髪完了 2

[7302088] 散髪開始 3

[7012360] 来店 6

[7012360] 来店 7

[7012360] 満席で立ち去る 7

[7012360] 来店 8

[7012360] 満席で立ち去る 8

[7302088] 散髪完了 3

[7302088] 散髪開始 4

[7302088] 散髪完了 4

[7302088] 散髪開始 6

[7302088] 散髪完了 6

[7302088] 床屋、眠る

[7012360] 来店 9

[7302088] 床屋、目覚める

[7302088] 散髪開始 9

[7012360] 来店 10

[7012360] 来店 11

[7012360] 来店 12

[7012360] 満席で立ち去る 12

[7302088] 散髪完了 9

[7302088] 散髪開始 10

[7012360] 来店 13

[7012360] 来店 14

[7012360] 満席で立ち去る 14

[7012360] 来店 15

[7012360] 満席で立ち去る 15

[7302088] 散髪完了 10

[7302088] 散髪開始 11

[7012360] 来店 16

[7302088] 散髪完了 11

[7302088] 散髪開始 13

[7302088] 散髪完了 13

[7302088] 散髪開始 16

[7302088] 散髪完了 16

[7302088] 床屋、眠る

※ 16人のうち 10人を散髪

 

化学反応式の完成 (Nested Flatten)

整数の係数を持つ化学反応式を完成してください。反応前の物質と反応後の物質は与えられる物とします。例えば、

(前) Mg, O 2 (後) Mg O

(答) 2Mg + O 2 -> 2MgO

(前) C 2, H 2, O 2 (後) CO 2 , H 2 O

(答) 2C 2 H 2 + 5O 2 -> 4CO 2 + 2H 2 O

こんな感じです。以前anarchy golf に出題させて貰ったんですが、埋め込み解で解かれてしまったので、今回は埋め込み解はなし、と云うことでおねがいします。

復活 (Nested Flatten)
現在のプロセスが終了後、一定時間経過したのち再起動するプログラムを作成してください。一時的にスリープするのではなく、プロセスAが一度終了しアンロードされてから別のプロセスA'が動き出す感じです。AとA'が時間的に重ならないことを要件とします。

プロセスが作成できない言語では、スレッドやオブジェクトなど適当に読み替えてください。

以下のどちらでもかまいません。下のほうが難しいと思います。
 <レベル1> 自分から終了して再起動する。
 <レベル2> タスクマネージャーや kill などでいきなり殺されたのち、再起動する。
UTF-16をUTF-8に変換 (Nested Flatten)

UTF-16の文字コードを16進(1オクテットごとにスペース区切り)の形で入力します。入力した文字コードを、2進数の形(1オクテットごとにスペース区切り)で出力してください。

入力する文字コードはUCS-2の範囲(サロゲートペアを使わなくてもよい範囲)のみに限定しても構いませんが、可能ならばサロゲートペアにも対応したものに挑戦してください。

  • 例1: abc(U+0041 U+0042 U+0043)
    • 入力 00 41 00 42 00 43
    • 出力 01000001 01000010 01000011
  • 例2: あいう(U+3042 U+3044 U+3046)
    • 入力 30 42 30 44 30 46
    • 出力 11100011 10000001 10000010 11100011 10000001 10000100 11100011 10000001 10000110

正攻法からトリッキーな手段まで、いろいろお待ちしております。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <stdio.h>                  
#include <stdlib.h>                 
#include <string.h>                 

typedef unsigned short utf16char; /* sizeof(short) >= 2 octets */
#define UTF8_MAXOCTETS 3 /* UCS-2ではutf-8にしたとき3 octets以内に収まる */
typedef struct{                                                           
        int len;                                                          
        char data[UTF8_MAXOCTETS];                                        
} Utf8char;                                                               

void encode(Utf8char *utf8, utf16char utf16){
        int i, len;                          

        if(!(utf16 & (~0x7f))) len = 1;
        else if(!(utf16 & (~0x7ff))) len = 2;
        else len = 3;                        

        switch(len){
        case 1:     
                utf8->data[0] = utf16 & 0x7f;
                break;                       
        case 2:                              
                utf8->data[0] = (utf16>>6 & 0x1f) | 0xc0;
                utf8->data[1] = (utf16 & 0x3f) | 0x80;   
                break;                                   
        case 3:                                          
                utf8->data[0] = (utf16>>12 & 0xf) | 0xe0;
                utf8->data[1] = (utf16>>6 & 0x3f) | 0x80;
                utf8->data[2] = (utf16 & 0x3f) | 0x80;   
                break;                                   
        }                                                
        utf8->len = len;                                 
}                                                        

void print_bin(char c){
        printf("%d%d%d%d%d%d%d%d ", c>>7&1, c>>6&1, c>>5&1, c>>4&1, c>>3&1, c>>2&1, c>>1&1, c&1);
}                                                                                                

int main(int argc, char **argv){
        int bytes = argc-1, len = bytes / 2;
        int i, j;
        utf16char *utf16;
        char *utf8;
        int u8len = 0;
        Utf8char u8char;

        if(!bytes) return 0;
        if(bytes % 2){
                printf("Invalid input.\n");
                return 1;
        }
        utf16 = malloc(sizeof(utf16char)*len);
        utf8 = malloc(len*UTF8_MAXOCTETS);

        for(i=0,j=1;i<len;i++,j+=2) utf16[i] = strtol(argv[j], NULL, 16)<<8 | strtol(argv[j+1], NULL, 16);

        for(i=0;i<len;i++){
                encode(&u8char, utf16[i]);
                memcpy(utf8 + u8len, u8char.data, u8char.len);
                u8len += u8char.len;
        }
        for(i=0;i<u8len;i++) print_bin(utf8[i]);
        putchar('\n');

        free(utf16);
        free(utf8);
}
いちばん長いしりとり (Nested Flatten)
単語のリストを読み込んで、そのリストにある単語で「しりとり」をします。
一番長くしりとりを続けるためのプログラムを書いてください。
また、単語数に対して、計算量がどのように増えていくかも考えて下さい。

なお、単語リストの一例として
http://www.ais.riec.tohoku.ac.jp/lab/wordlist/index-j.htmlで公開されている
http://www.ais.riec.tohoku.ac.jp/lab/wordlist/fam55_40.txtがあります。

ただし、
・一度使った単語は使わないこと(リストに重複がある可能性は考えなくてよい)
・「ん」で終わる単語を使用するか、リスト内にしりとりを続けられる単語がなくなったときに、しりとりは終了する
・一番最初は、好きな単語から初めてもよい
・「一番長くしりとりを続ける」とは、しりとりが終了するまでに使用する単語数が最大になるよう、しりとりの単語を選ぶことをいう
リングノードベンチマーク (Nested Flatten)

N個のノードを作り、1番目のノードに送られたメッセージは2番目のノードに、2番目のノードに送られたメッセージは3番目のノードに、・・・、N番目のノードに送られたメッセージは1番目のノードに送られるようにリングを形成し、そのリング上を一つのメッセージがM回まわるのにかかる時間を計測してください。

メソッド数の多い組み込みクラスを列挙 (Nested Flatten)

言語処理系に組み込みの全クラスについて、それぞれに定義されているメソッド数が多い順に上位10番目までのクラス名とメソッド数を出力するコードを書いてください。全クラス数も示してください。

なお、「組み込み」「クラス」「メソッド」などについては、必要であれば、その言語にふさわしい対象や機能に適宜読み替えてください。(たとえば、組み込み→標準添付、クラス→型・モジュール・パッケージ…、メソッド→関数・プロシージャ…といった具合に)

初期設定の読み書き (Nested Flatten)

 初期設定を読み書きするプログラムを書いてください。

 保存先や形式は問いませんが,OS,ライブラリ,言語等の環境で標準的なものがあれば,なるべくそちらを用いてください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package org.doukaku.ja.preference;

import java.util.prefs.Preferences;
import java.util.prefs.BackingStoreException;

public class HelloPreference {
    private static final String MESSAGE_KEY = "message";
    private static final String DEFAULT_MESSAGE = "Hello, Preference.";

    private String message;
    private Preferences pref;

    public HelloPreference() {
        loadPreference();
    }

    public void loadPreference() {
        setPreference(Preferences.userNodeForPackage(this.getClass()));
        setMessage(pref.get(MESSAGE_KEY, DEFAULT_MESSAGE));
    }

    public void setMessage(String message) { this.message = message; }
    public String getMessage() { return this.message; }
    public void setPreference(Preferences pref) { this.pref = pref; }
    public Preferences getPreference() { return this.pref; }

    public void showMessage() {
        System.out.println(getMessage());
    }
    public void storePreference() throws BackingStoreException {
        Preferences pref = getPreference();
        pref.put(MESSAGE_KEY, getMessage());
        pref.flush();
    }

    public static void main(String[] args) {
        try {
            HelloPreference    hello = new HelloPreference();
            if (args.length > 0) {
                hello.setMessage(args[0]);
            }
            hello.showMessage();
            hello.storePreference();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
printf書式変換 (Nested Flatten)
C言語のprintf書式を、あなたの言語のprintf系書式に変換して下さい。
また、逆変換をして下さい。
loan patternのサンプル (Nested Flatten)
リソースを使うときのパターンloanのサンプルを書いて下さい。
参考
Programming in Scala (P.170 , P.172)
手作業Grep (Nested Flatten)

標準入力を読み込んで、行選択のUIをだし、選択されたものだけを標準出力にだしてください。 標準出力に出力するタイミングは選択終了をユーザーが報告したときです。(完了ボタンを想定してください)

UIライブラリは何をつかってもかまいません。 例えばncursesのようなコンソール上でのUIでもかまいませんし、GtkのようなGUIライブラリでもかまいません。

想定される使い方としては、以下のような感じです。

ps aux | handgrep | xargs kill -9

プロセスの一覧を表示、UI上で選択したものをkill

ストレンジアトラクタの描画 (Nested Flatten)
ストレンジアトラクタの描画をしてください。
ストレンジアトラクタの種類は問いません。
簡単に出力できる言語はその言語の出力機能を使ってもらってかまいません。
また、出力が難しい言語はgnuplotなどのグラフ出力ソフトを使って出力してください。

解答の際はどのタイプのストレンジアトラクタなのかを添えてください。
急勾配の判定 (Nested Flatten)

有限の長さの数列で,各要素の値が,その要素の後ろにある残りの列に含まれるすべての要素の和よりも大きい列を「急勾配の列」ということにします(空列の和は0とします).

任意の長さ(ただし有限の長さの)数列を与えられたとき,それが「急勾配の列」であるかどうかを判定する述語関数を定義してください.

必須ではありませんが,効率についてコメントがあれば面白いかもしれませんね.

複素数 (Nested Flatten)
以下の計算をしてください。

1. 加算  ( 3 + i ) + ( 4 - i )
2. 減算  ( 5 - 9i ) - ( 2 + 6i )
3. 乗算  ( 5 + 3i )  * ( 5 + 8i )
4. 除算  ( 9 - 7i )  /  ( 9 - 3i )
5. 絶対値  | 2 + 3i |

複素数計算を行う関数やクラスを定義して答えを求めること。
ライブラリがある場合はそれを利用してかまいません。
割り算の筆算 (Nested Flatten)
整数 n, m を与えれば、 n ÷ m の筆算を出力するような
プロシージャ(関数)を創ってください。

ウィンドウに描画するもよし、
コンソールに出力するもよし、です。
例外処理 (Nested Flatten)

例外処理の適当なサンプルを書いてください。

但し、言語によって例外処理がサポートされている場合はそれを利用してください。

外部の実行ファイルを呼び出し (Nested Flatten)
外部の実行ファイルを呼び出して実行してください。
ただし、実行中にプログラムの実行をブロックする版と、しない版の二つを作ってください。
ダブルクリックの取得 (Nested Flatten)
マウスのダブルクリックを取得してください。
ダブルクリックを取得したら、ダブルクリックをした時のマウス座標を表示してください。
キッチンタイマー (Nested Flatten)
キッチンタイマーを作ってください。
要件は以下のとおりです。

・タイマーが鳴るまでの時間を入力可能
・残り時間を表示
・タイマーが切れたら音がなる
ナイツ関数(ボケの方) (Nested Flatten)
入力した文章のところどころを言い間違えて出力する関数を実装してください。
(ナベアツ算を見てて思いつきました)

入出力の方法は標準入出力や引数・戻り値など、扱いやすい方法でかまいません。

文字単位でランダムに間違えても面白くないので、単語のリストから似た単語の候補を探すようにしてください。英単語でもOKです。単語のリストは参考ページからダウンロードしたものを加工して利用すると良いと思います。(4000個あります)

結果がつまらなくても構いませんが、面白いボケをうむ工夫があると良いです。
※人が考えたボケは求めてませんよ!

入力の例として「どう書く?org」の前文をお借りしました。ご自分でヤホーで調べたりして手ごろな文章を見つけて下しあ。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<入力例>
ドウカク org ヘ ヨウコソ
コノ サイト ハ ダサレタ オダイ ヲ イカニ トクカ キソイアウ
 プログラマ ノ タメノ コロシアム デス
トウコウ ヲ タメシテ ミタイ カタ ハ テスト
トリアエズ ナガメテ ミタイ カタ ハ ゲンゴ ノ イチラン ガ オススメ デス

<出力例>
ドウモク org ヘ ヨウコソ
コノ ザレゴト ハ ダサレタ オダイ ヲ イワハダ トシシタ キソイアウ
 プログラマ ノ タチノミ コロシアム デス
トウコウ ヲ ハナシテ ミチノリ カタ ハ プリント
トリアエズ ナガメテ ミツリン カタ ハ ゲンゴ ノ キンラン ガ オススメ デス
麻雀の和了判定 (Nested Flatten)
麻雀の手牌が和了形か否かを判定するコードを書いてください。

手牌を表すのは、mn+h 枚を表す配列です。フォーマットは A, B の2つから任意に選んだものを受け取ってください。以下の2つは同じものです:
handA = [2,1,1,1,1,2,2,1,3] # 牌1が2個、牌2が1個、牌3が1個、牌4が1個、牌5が1個、牌6が2個、牌7が2個、牌8が1個、牌9が3個
handB = [1,1,2,3,4,5,6,6,7,7,8,9,9,9] # 牌1、牌1、牌2、牌3、牌4、牌5、牌6、牌7、牌7、牌8、牌9、牌9、牌9

ある配列が和了形であるとは、手牌が「刻子」「順子」を合計 n 個と「対子」1 個との和であることをいうものとします。
「刻子」とは1種の牌が m 個あることをいいます。
「順子」とは連続したインデクスを持つ牌が m 種各1個あることをいいます。
「対子」とは1種の牌が h 個あることをいいます。

上の例は、和了形です。なぜなら、当該配列が
Bタイプで表記すると、刻子 [9,9,9], 順子 [2,3,4], [5,6,7], [6,7,8], 対子 [1,1] の、
Aタイプで表記すると、刻子 [0,0,0,0,0,0,0,0,3], 順子 [0,1,1,1,0,0,0,0,0], [0,0,0,0,1,1,1,0,0], [0,0,0,0,0,1,1,1,0], 対子 [2,0,0,0,0,0,0,0,0] の、
和だからです。

・ n は任意のものを受け取れるようにしてください。
・ 牌のインデクスの数 (Aタイプの長さ、Bタイプの要素の最大値) M も任意としてください。
・ 1種の牌の最大個数 (Aタイプの要素の最大値、Bタイプの1種の要素の最大重複度) L も任意としてください。
・ 一般の麻雀の場合は、m=3, n=4, h=2, M=9, L=4 です。この条件に特化した高速化が可能なら行ってもかまいません。

擬似コードで、ごく短い例を示します。
1
2
3
4
5
6
7
8
for 考えられる対子:
    対子を手牌から抜く
    for 考えられる刻子のパターン:
        刻子を手牌から抜く
        手牌が順子の和となっていれば、和了形として抜ける
        刻子を手牌へ戻す
    対子を手牌へ戻す
ここに到達していれば、和了形ではない
17歳教 (Nested Flatten)

誕生日を入力すると、「17歳と何日か」、「17歳と何か月と何日か」を表示するプログラムを作ってください。

ナベアツ算 (Nested Flatten)

「3の倍数と3がつく数字の時だけアホになる」コードを実装して下さい。

また、余裕のあるかたは更に、

「8の倍数のときに人探しをしてる感じに」「5の倍数のときにナルシストに」なるよう実装して下さい。

指定ファイル名でフォルダツリーごとコピー (Nested Flatten)
コピー元フォルダ、コピー先フォルダ、ファイル名(複数)を指定し、
コピー元フォルダ(配下含む)から、指定したファイル名のファイルを探し出し、
コピー先フォルダにツリーごとコピーする処理を実装して下さい。

[実装に際して]
・複数ファイル名を指定できればどのような形式でも構いません。
   (例: コマンド引数, 外部ファイル)
・指定したファイル名が複数見つかった場合、すべてコピー対象として下さい。
・コピー先に既にファイルやフォルダが存在する場合、削除して下さい。
   (コピー先が指定したファイルのみとなるようにする)
・コピー先フォルダが存在しない場合、新規作成して下さい。

[余裕のある方は]
・除外するファイル名、フォルダ名を指定できるようにして下さい。
・GUIでファイル名の指定やコマンド実行を行えるようにして下さい。

===============================
例) コマンド引数で指定する
(コマンド {コピー元} {コピー先} {コピーファイル名リスト})
>WholeCopy C:\temp C:\temp2 aaa.txt,ddd.txt,ggg.txt,kkk.txt

[フォルダツリーの状態]
C:\temp
|   aaa.txt
|   bbb.txt
|   ccc.txt
|
\---dir1
    |   ddd.txt
    |
    +---dir2
    |   |   eee.txt
    |   |
    |   \---dir3
    |           fff.txt
    |           ggg.txt
    |
    \---dir4
            hhh.txt
            iii.txt
            jjj.txt
            kkk.txt

C:\temp2
|   aaa.txt
|
\---dir1
    |   ddd.txt
    |
    +---dir2
    |   \---dir3
    |           ggg.txt
    |
    \---dir4
            kkk.txt
===============================
作業予定表から週単位で作業量を積み上げる (Nested Flatten)
以下のような期間を表す予定データから、1週間単位での棒グラフになるように作業量を積み上げて表示して下さい。
余裕があれば、土日祝日を休日として、終了日を後ろにずらした表示にすると良いですね。

    開始日    日数
1.2009/1/10 21日間 (#) ←わかり易いように記号を付けています
2.2009/1/15  6日間 (@)
3.2009/1/10  8日間 (*)
4.2009/1/16  1日間 (=)
5.2009/1/16  3日間 (%)
6.2009/1/30  4日間 (=)

結果例:

           %
           %
           %
           =
           *
           *
           *
           *
           *
           *
           @
           @   %
           @   @
           @   @
           #   #   =
           #   #   =
           #   #   #
      *   #   #   #
      *   #   #   #
      #   #   #   #
      #   #   #   #
 1/1  1/5  1/12 1/19 1/26

ルール:
・下から上に向かって積み上げて下さい
・結果の表示は、記号でなくても、テキストでなくても構いませんが個々の予定が判別出来るようにして下さい
・表示範囲は1ヶ月(1/1~1/31)とします
 表示範囲からはみ出した分は無視します
・1週間は月曜から日曜までとします
・予定は1日単位とします

このお題は、以前仕事で作った機能のほんの一部を抜き出して単純化してみました。
プロジェクト管理等でよくあるグラフですね。
エレベータの制御(基本編) (Nested Flatten)
エレベータを制御して、5階建てのビルの各階にいる人たちを、
「効率よく」1階のエントランスまで運んでください。

作成時の条件は次の通りです。
  1. 各階において、人が残っていることはわかるが、
     あと何人残っているかまではわからないものとする。
     # 人が残っているところは常に呼び出しのボタンが押された状態を
     # 仮定して問題ありません。
  2. 稼働しているエレベータは1機のみとする
  3. 降車するたびに、変化がわかるような出力をしてください。
  4. すべての人を運搬終わったら、最後に次の情報を出力してください。
     - 運搬を始めてからの経過時間(ラウンド数)
     - 一番長く放置されていた階の待ち時間(ラウンド数)
     - エレベータの移動距離合計数

エレベータの機能は次の通りです。
  - 搭載人数は最大3人までとする。
  - 移動には、1つの階につき「2」ラウンドかかる。
  - 人の乗降には、1回につき「5」ラウンドかかる。

※ 「ラウンド」は包括された時間だと思ってください。
   単純に「秒」と読み替えてもよいです


各階の人数は次の通りです。
5階  7人
4階 11人
3階  3人
2階  7人
1階  0人

冒頭では、「効率よく」なんて曖昧な表現をしようしましたが、
何について効率よくしたのか、設計についての見解を
コメントしていただけるとうれしいです。

たとえば、
下記のサンプル出力では、各階の待ち時間を最小とすることで
効率よいとしました。(利用者の視点)
ぱっと思いつくところでは、ほかにも2-3種類あるとおもいます。

さて、あなたならどう書く?(笑
// 自分で作ったやつは250L位になってしまいましたorz

INIT --------------------
 [5]th Floor: [ 7] / last_round:[   0]
 [4]th Floor: [11] / last_round:[   0]
 [3]th Floor: [ 3] / last_round:[   0]
 [2]th Floor: [ 7] / last_round:[   0]
 [1]th Floor: [ 0] / last_round:[   0] 

IN(5) [7] → [4] OUT
IN(4) [11] → [8] OUT
IN(3) [3] → [0] OUT
IN(2) [7] → [4] OUT
IN(5) [4] → [1] OUT
IN(4) [8] → [5] OUT
IN(2) [4] → [1] OUT
IN(5) [1] → [0] IN(4) [5] → [3] OUT
IN(2) [1] → [0] OUT
IN(4) [3] → [0] OUT

END --------------------
 [5]th Floor: [ 0] / last_round:[ 174]
 [4]th Floor: [ 0] / last_round:[ 229]
 [3]th Floor: [ 0] / last_round:[  58]
 [2]th Floor: [ 0] / last_round:[ 213]
 [1]th Floor: [ 0] / last_round:[   0] 
       経過時間:[257]
   最大待ち時間:[100]
 移動距離合計数:[52]
データの圧縮と展開 (Nested Flatten)

データを圧縮するcompress、展開するdecompressという関数やメソッドなどを書いてください。データはバイト列でもストリームでもそれ以外の形式でもOKです。

圧縮形式は問いませんが、できるだけ一般的なフォーマット(zip,lzhなど)でお願いします。

また、標準以外のライブラリを使う場合には出典の記載をお願いします。

「○○でも実用的な圧縮/展開プログラムがかけるんだぞ!」というのを、ぜひ示してください。

麻雀ゲーム1 (Nested Flatten)

麻雀ゲームの部分的な作成がお題になります. 以下のメソッド/関数を組み込んで下さい.

  1. n人のプレーヤでゲームをする機能; n = 2--4.
  2. 牌をかき混ぜてから山を作成する機能.
  3. 手牌を理牌する機能.
  4. 山から牌を取る操作.
  5. 手配を切る操作 (ツモ切りで構いません).
  6. 河を保存する機能.
  7. 3--5を繰り返す機能.

ルールとしては,

  1. 配牌は親は14枚, 子は13枚.
  2. 親から順に手牌を切る.
  3. 自分の手番で始めにツモり, その後手牌を切る.
  4. 手牌の数は最大14枚.
  5. 山の牌が残り14枚になったら終了.
  6. 牌全体としては, (3人プレーヤでも) 日本で通常用いられている34種類136枚を使用.

と考えていただければ結構です.

鳴き, あがり, 自風, 場風などは考慮していただかなくて結構です.

テキスト行の正規化 (Nested Flatten)
改行文字を複数個含むテキストデータを格納する文字列を
最大長の行を除く各行末に指定したパディング文字を適切な数だけ追加して、
すべての行が最大長の行と同じ長さに揃う文字列に変換する
手続あるいは関数を書いてください。

元の文字列の最後は改行です。
行の長さはその行に含まれる(行末の改行を除く)文字の数です。

変換前の文字列例
"○○○○\n○○○○○○○\n\n○○○○○\n"

上の文字列例をパディング文字'☆'を指定して変換した文字列
"○○○○☆☆☆\n○○○○○○○\n☆☆☆☆☆☆☆\n○○○○○☆☆\n"

必須ではありませんが、
テキストデータをトラバースする回数を減らす工夫をすると面白いかもしれません。
道順を数える (Nested Flatten)
図.1のような。格子状の経路があるとします。

(1)  このときPからQまでいくのに何通りの経路があるか数えてください。ただし遠回りはせずかならずQに近づく方向に進む(右方向か下方向にだけ進む)とします。

(2)  (1)と条件は同じで、図.2のように経路の一部がない(通れない)場合に、PからQまでいくのに何通りの経路があるか数えてください。

P-+-+-+    P-+-+-+
| | | |    | | | |
+-+-+-+    +-+-+-+
| | | |    |   | |
+-+-+-+    +-+-+ +
| | | |    | | | |
+-+-+-+    +-+ +-+
| | | |    | | | |
+-+-+-Q    +-+-+-Q
  図.1       図.2

経路の表現の仕方、記憶の仕方は自由とします。上記のようなキャラクタでの表現でもよいですし、最初からプログラムで扱いやすいデータとして持っていてもOKです。入力も外部からの入力でもよいですし、プログラム中にコーディングされていてもOKです。


※問題は、野﨑昭弘「離散数学『数え上げ理論』」(講談社 ブルーバックス)「第3章 道順を数える」から拝借させて頂きました。
数独の問題数を数え上げる (Nested Flatten)
4×4のマスを2×2の4ブロックに区切り、いくつかのマスに1~4の数字を配置します。

以下、空白のマスすべてに数字を補い、縦、横、および各ブロックについて1~4の数字が
それぞれ一個ずつ含まれている状態にすることが可能で、かつその方法が一意であるもの、
つまり数独の問題として成立するもののみを考えます。

4 1 | 2           4 1 | 2 3
2   | 4 1         2 3 | 4 1
----+-----  --->  ----+----
  2 | 3 4         1 2 | 3 4
3 4 | 1           3 4 | 1 2

このようなものの総数を「初期配置の数字の個数ごとに」カウントしてください。

余力のある人は、極小な配置に限定してカウントしてみてください。
ただし、極小な配置とは、どの数字を取り除いても数独の問題として
不成立になる配置を指すものとします。


まどろっこしい言い回しになってしまいましたが、
一言で言えば「数独の問題数を数え上げよ」という問題になります。

参考:http://ja.wikipedia.org/wiki/%E6%95%B0%E7%8B%AC
行列式の計算 (Nested Flatten)

n×nの2次元配列を引数にとり、 これを行列とみなして行列式を返す 関数を作成してください。

行列・線形代数のライブラリ等を 使用しないことが条件です。

参考:http://ja.wikipedia.org/wiki/%E8%A1%8C%E5%88%97%E5%BC%8F

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# -*- coding: utf-8 -*-

#   定義に基づく実装例


#   対称群
def symmetric_group(n):
    #   配列 [0, 1, .., (n-1)] を並び替えてできる
    #   すべての配列の組み合わせを返します。

#  置換の符号
def signature(sym):
    #   配列 [0, 1, .., (n-1)] の符号を +1とします。
    #   互換(2つの要素を交換)すると符合が変わります。
    #   配列 [0, 1, .., (n-1)] から
    #   奇数回の互換で得られる配列の符号は -1、
    #   偶数回の互換で得られる配列の符号は +1 になります。

#  行列式
def determinant(mat):
    det = 0;
    deg = len(mat)
    for s in symmetric_group(deg):
        term = signature(s)
        for i in range(deg):
            term *= mat[i][s[i]]
        det += term
    return det
inline/embeded bytecode assembly (Nested Flatten)

Duff's deviceをinline bytecode assemblyを使って実装してください。C言語ではよくあるinline asmのほかの言語バージョンといったところです。copyのsrcとdstは呼び出し側から渡すようにしてください。(要はbytecode側で閉じていてはならない)

Duff's deviceとは、 http://ja.wikipedia.org/wiki/Duff%27s_device に説明がありますが、ループ展開したコピーのコードです。もちろんbytecodeである時点で速度の話をするのはナンセンスです。

bytecodeで速くするとかいう話よりも、ある言語で書かれたcodeの中にその言語で使用されているbytecodeが埋め込めるかどうか、どのようにできるのかが、このお題の意図です。面白い使い道があるならsiteしていただけると幸いです。

また、1言語につき1種のbytecodeとは限りません。たとえば、PythonならCPythonのbytecode, JythonのJavaVMのbytecode, IronPythonのCIL/CLRなどがあります。 もちろん特定アーキテクチャのasmを呼んでもよいです。x86を書くことができるpyasmなんてものもあるらしいです。 http://members.verizon.net/olsongt/usersGuide.pdf

疑似並行処理 (Nested Flatten)

数値(たとえば1から10)と、アルファベット(たとえばAからJまで)を順に出力する別々のループ処理を並行に実行させ、共通の出力先に出力する極力シンプルなコードを書いてください。

念のため、実行後、出力先に数値とアルファベットが混ざって出力されている(たとえば、数値がすべて出力されてからアルファベットが続く…というふうになっていない)ことを確認してください。混ざってさえいれば、それぞれ1文字ずつ交互である必要はありませんし、もちろん交互でも構いません。

出力先や出力方法は自由です。標準出力、テキストファイル、コンテナオブジェクト(配列、リスト、コレクション)など使いやすいもので構いません。

例として Squeak Smalltalk でのコードと結果を示します。シンプルなコードなので Smalltalk に馴染みがない人も、おおよその内容は掴めると思います。

1
2
3
4
5
6
7
| out |
out := OrderedCollection new.

[(1 to: 10) do: [:each | out add: each. Processor yield]] fork.
[($A to: $J) do: [:each | out add: each. Processor yield]] forkAndWait.

^out asArray  "=> #(1 $A 2 $B 3 $C 4 $D 5 $E 6 $F 7 $G 8 $H 9 $I 10 $J) "
'('と')'の対応 (Nested Flatten)

入力の'('と')'の対応をとってください。

ただし、コード中に'('と')'を含まないでください。

漢字の九九にinspireされました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import sys
start = sys.argv[1]
end = sys.argv[2]
to_test = sys.argv[3]
print start
print end
print to_test

stack = []
while to_test:
  print stack
  head = to_test[0]
  to_test = to_test[1:]
  if head == start:
    stack += [head]
  if head == end:
    if stack:
      stack = stack[:-1]
    else:
      stack = [True]
      break
if stack:
  print False
else:
  print True
世界時計 (Nested Flatten)
プログラムを実行した端末のロケールと、グリニッジ標準時と、ロサンゼルスの現在時刻をそれぞれ表示してください。 時刻の表示はリアルタイムでなく、一回限りで構いません。 時刻のフォーマットは自由とします。
1
2
3
4
出力例
現在の時刻は、2008年10月29日 11時36分21秒です。
グリニッジ標準時刻は、2008年10月29日 2時36分21秒です。
アメリカ・ロサンゼルスの時刻は、2008年10月28日 19時36分21秒です。
π (Nested Flatten)

円周率を計算してください。

積分を計算するも、素朴な方法も、速さを目指すも、LLで計算する意味を問うもあるでしょう。

http://ja.wikipedia.org/wiki/%E5%86%86%E5%91%A8%E7%8E%87

タブ区切りデータの処理 (Nested Flatten)

タブ区切りのデータを読み込んで操作をし書き出す方法を教えてください。 読み込み・書き出しの方法は任意とします。

与えられるデータは:

  • レコードの区切りは改行、カラムの区切りはタブです。
  • 最初のレコードはヘッダで、カラムの名前が書いてあります。
  • それ以降はデータで、第1,4カラムは整数値、第2,3カラムは文字列値です。

この入力データに対して以下の操作をしたものを書き出してください:

  • 第1カラムの値でデータを昇順にソートする。
  • 第2カラムと第3カラムをヘッダを含めて入れ替える。
  • 第4カラムの値にそれぞれ1を加える。

入力の例:

ID      Surname Forename        Age
1       Sato    Hanako  17
0       Suzuki  Taro    18
...

出力の例:

ID      Forename        Surname Age
0       Taro    Suzuki  19
1       Hanako  Sato    18
...
LL Golf Hole 9 - トラックバックを打つ (Nested Flatten)

LL Golf Hole 9のリリースをアナウンスしているエントリにトラックバックを打ってください(トラックバックURL)。マシンガンのようには打たないでください。ただし、このエントリにはスパムフィルタが搭載されているため、寄せることはできてもカップインできないかもしれません。その場合はtakano32が用意させていただきました打ちっ放し場にてガンガン試し打ちください(トラックバックURL)。

余力のあるものは感想を公式ブログ感想エントリにトラックバックくしてください。 余力がなくても感想をトラックバックしてくれるとスタッフがよろこびます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/env ruby
require 'net/http'
require 'uri'
uri = URI.parse('http://ll.jus.or.jp/2008/blog/archives/38/trackback')
Net::HTTP.start(uri.host) do |http|
    ping = "title=LL+Futureに行ってきた!&" +
        "excerpt=参加者としてもLL+Futureおもしろかったよ!¥n" +
        "でも、司会ぐだぐだですみません。次から頑張ります!&" +
        "url=http://ja.doukaku.org/207/&" +
        "blog_name=LL+Golf+Hole+9"
    response, = http.post(uri.path, ping)
    puts response.body
end
2^i * 3^j * 5^k なる整数 (Nested Flatten)

2^i * 3^j * 5^k の形で表される整数を小さい方から順に 100 個列挙するプログラムを書いてください。 i, j, k は 0 以上の整数です。アルゴリズムのオーダーについても考えてみてください。

例えば最初の 10 個は次のようになります:

 1 = 2^0 * 3^0 * 5^0
 2 = 2^1 * 3^0 * 5^0
 3 = 2^0 * 3^1 * 5^0
 4 = 2^2 * 3^0 * 5^0
 5 = 2^0 * 3^0 * 5^1
 6 = 2^1 * 3^1 * 5^0
 8 = 2^3 * 3^0 * 5^0
 9 = 2^0 * 3^2 * 5^0
10 = 2^1 * 3^0 * 5^1
12 = 2^2 * 3^1 * 5^0

※解答では i, j, k の各値を示す必要はありません。

起動オプションの解析 (Nested Flatten)
いわゆる、コマンドライン引数の取得(http://ja.doukaku.org/118/)からの派生です。
やっぱ、自分のコマンドってオプションつけたいですよね(笑
タグに「クックブック」なんてつけてみました
長文なのはご容赦ください^^;;
-----
次の起動インタフェースを持つコマンドを作成してください。

書式:cmdopt -o [-q] -d{0|1|2} 文字列 [文字列 ...]

書式を説明すると
- オプション「o」
  必須オプションです。指定されていない場合、異常終了してください。
- オプション「q」
  選択オプションです。
  省略されていても問題有りません。
- オプション「d」
  引数付きオプションです。
  「0」「1」「2」のいずかが続いて指定されます。
- 文字列
  パラメータです。
  1つ以上であればいくつでも指定できます。
  指定されていなかった場合、異常終了してください。

オプションの開始が「-」になっていますが
「+」や「/」でもかまいません。
余力があればロングオプションに対応してもよいです。

起動例:(すべて許容されるのが望ましいです)
1. cmdopt -o AAA
2. cmdopt -o AAA BBB CCC
3. cmdopt -oq AAA
4. cmdopt -o  -q AAA
5. cmdopt -o -s1 AAA
6. cmdopt -o -s 1 AAA
7. cmdopt -q -s2 -o AAA

出力例:
[オプション情報]
o(output): ON|OFF
q(quote): ON|OFF
d(debug): 0|1|2 

[パラメータ情報]
指定数: N
1: 文字列1
2: 文字列2
...
N: 文字列N
tailの実装 (Nested Flatten)

'tail'を実装してください。

巨大なファイルでも効率的に動作するようにしてください。

最低限必要な機能は、

  • 行数指定
  • 「-f」パラメータの対応

です。

lessの実装 (Nested Flatten)

'less'を実装してください。

巨大なファイルでも効率的に動作するようにしてください。

最低限必要な機能は、

  • 上下スクロール
  • 検索

です。

クリップボードへの転送 (Nested Flatten)

クリップボード(や同等の機能)へテキストを転送するプログラムをお願いします。 また可能でしたらクリップボードのデータを取り出すプログラムもお願いします。

システムに依存する内容ですが、応用範囲が広いと思いましたので出題させてもらいました。

コード中の文字の頻度分析 (Nested Flatten)

プログラムコード中の文字の頻度は言語によって相当にばらつきがあると思います。ある言語はピリオドが頻出するとか、別の言語はカッコの頻出頻度が高い、とか。そこで、

  • 文字の頻度解析をするプログラムを作成し、
  • 適当なプログラムに対して実行し、結果を出力して、そのような頻度になっている理由を教えてください。

(その言語で書かれた「典型的な」プログラムコード、といえるようなものがあると良いのですが・・)

簡単すぎるという方は、複数文字にしてみたり単語の頻度にしてみてください。

参考;Wikipedia 頻度分析

http://ja.wikipedia.org/wiki/%E9%A0%BB%E5%BA%A6%E5%88%86%E6%9E%90

出力の一時停止と再開 (Nested Flatten)

起動すると、標準出力に1秒毎に'a'の1文字を出力し続けるプログラムで、 以下の条件を満たすものを「どう書く?」

  • 'q'キーが押されるとプログラムは終了する
  • 出力中に'p'キーが押されると一時停止する
  • 一時停止中に'p'キーが押されると出力を再開する
マルバツゲーム:賢いプレイヤー (Nested Flatten)
#6190 の続編です。
マルバツゲームで、賢いプレイヤーの思考ルーチンを実装してください。

賢いといってもいろいろありますが、
1.負けない
2.できるだけ勝つ
という条件でいってみたいと思います。

ランダムプレイヤーと1万回バトルした結果(勝ち・負け・分け)を表示してください。
先攻になっても後攻になっても無敗!となれば言うことなしです。
α置換 (Nested Flatten)
標準入力から与えられたソースコードの変数名
を置換するプログラムを作ってください。
最近はリファクタリングツールなどの普及でこ
のような需要は少ないかと思われますが、viな
ど貧弱なエディタを使っているときに困る
のが変数名の置換です。さすがに以下の例のよ
うなプログラムは例としてしか書きませんが、
置換しようとしている変数名と同じ綴りの他の
ものがプログラム中に出てくることはまれにあ
ります。そこで、与えられたソースコードに現
れる変数だけを指定された名前に置換してくだ
さい。
置換対象となるソースコードと使用言語は同じ
ものを使ってください。与えられるソースコー
ドは、完全なコンパイル単位、もしくはパース
して意味が通る範囲のものどちらであってもか
まいません。後者の場合、一番外側の変数だけ
置換できるようにしてください。
C言語での解答例をつけたかったのですが、と
ても難しかったためまだ作成できていません。
ご容赦ください。

例
$ cat a.c
/* a */
int foo()
{
        struct a {int a;} a;
#if FOO
        a.a = 1;
#endif
        { int a; }
	return 0;
}
$ alpha -DFOO=1 b a < a.c
/* a */
int foo()
{
        struct a {int a;} b;
#if FOO
        b.a = 1;
#endif
        { int a; }
	return 0;
}
メソッドのフック (Nested Flatten)

例えば、あるクラスのあるメソッドを実行する前に他の処理を呼びたい(例えばログやトランザクション開始など)。 また、そのメソッドの終了後にも何らかの後処理を呼びたい(トランザクション終了など)。

そのような、メソッドに対するフック処理を書いてください。 ライブラリを使用してメソッドのフックを実現した場合は ライブラリの名前を紹介してくれると助かります。

ポリゴンを表示するプログラム (Nested Flatten)
適当なポリゴンを表示させて、描画するプログラムを書いてください。
ポリゴンは回転させてください。

2D処理だけなら、標準ライブラリで大体いけますが、
3D処理は追加でライブラリを利用すると思うので、
何のライブラリを利用したのか書いてください。
不動点演算子 (Nested Flatten)

不動点演算子とは、関数を引数に取り、その関数の不動点を返すような関数です。 つまり、不動点演算子である関数gが関数fを引数に取るとき、 f(g(f)) = g(f) となります。

お題は不動点演算子を実装することです。(Yコンビネータを実装しても結構ですが、それ以外でも、コンビネータになっていなくてもOKとします)

総当たり戦の日程作成 (Nested Flatten)
任意の偶数Nのチームの総当たり戦を最短日数(N-1日)で行う場合の日程表を1つ作成してください。

解はひとつではない場合もあります。
もし、余力があれば、全ての可能性も求めてください。

これは、スポーツスケジューリングと言う分野の問題で、数学的には、カークマンの問題と言うのが近いようです。

例えば、4チームであれば、

1-2 3-4
1-3 2-4
1-4 2-3

6チームであれば

1-2 3-4 5-6 
1-3 2-5 4-6 
1-4 2-6 3-5 
1-5 2-4 3-6 
1-6 2-3 4-5

が解のひとつです。
ライフゲーム (Nested Flatten)
セルオートマトンに関するお題です. 
2次元タイプの'ライフゲーム'を実装して下さい. 
初期値としては10行10列程度の格子上の平面に0.3程度の人口(?)密度を考え, 
末端はループするようにして下さい. (例: 座標[-1, -1] = [10, 10])

それだけだと簡単すぎると思われる方は, 
過密状態で間引きが発生するような機能を組み込んで下さい. 
間引きは, 少なくともその後の1時間ステップにおける死亡率が, 
それをしなかった場合よりも小さくなれば結構です. 
(死亡率の最小化は複雑性が高すぎる感がありますし. )
サンプル:
t = 0
[ ][*][ ][ ][ ][ ][*][*][*][ ]
[ ][ ][ ][ ][*][ ][ ][*][*][ ]
[ ][ ][ ][*][ ][ ][*][ ][*][ ]
[*][ ][*][*][ ][ ][*][ ][ ][ ]
[ ][*][ ][ ][ ][ ][ ][ ][*][ ]
[*][ ][ ][ ][*][ ][*][*][ ][*]
[ ][*][ ][ ][ ][ ][*][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ][ ][*]
[*][ ][ ][ ][ ][ ][*][ ][ ][*]
[ ][ ][ ][ ][*][*][ ][ ][*][ ]
t = 1
[ ][ ][ ][ ][*][ ][ ][ ][ ][*]
[ ][ ][ ][ ][ ][*][ ][ ][ ][*]
[ ][ ][*][ ][*][*][*][ ][*][*]
[ ][*][ ][*][ ][ ][ ][ ][ ][*]
[ ][ ][*][*][ ][*][*][ ][*][ ]
[ ][*][ ][ ][ ][*][*][ ][*][*]
[ ][ ][ ][ ][ ][*][*][*][*][*]
[ ][ ][ ][ ][ ][ ][ ][ ][ ][*]
[*][ ][ ][ ][ ][*][ ][ ][*][ ]
[*][ ][ ][ ][ ][ ][ ][ ][ ][ ]
西暦 to 和暦 (Nested Flatten)
西暦を和暦に変換するプログラムを書いてください。元号の切り替わる日など、複数の表記が可能な場合には両方表示し、西暦が無効な日付の場合には「範囲外」と表示するようにしてください。対応すべき日付は明治元年以降とします。

>a.py 1868/12/2
明治1年12月2日

>a.py 1926/12/24
大正15年12月24日

>a.py 2007/12/01
平成19年12月1日

>a.py 1926/12/25
大正15年12月25日 昭和1年12月25日

>a.py 1868/1/2
範囲外

>a.py 1868/100/2
範囲外
ワーカスレッドを安全に終了させるまで待機 (Nested Flatten)

スレッドプールに複数のワーカスレッドが待機しており、メインスレッドはいつでもワーカスレッドに仕事を渡せるような状態になっているとします。

さて、メインスレッドからスレッドプールにいくつか仕事を与え、メインスレッドは与えた仕事すべてが終了するまで待機し、次の処理に行ってはいけない、というようなコードを書いてください。 #現実に書く機会が多そうなコードですね…。

ここでの仕事の内容は、適当に5秒から15秒の間スレッドをスリープする、というもので結構です。 また、ワーカスレッドのスレッドプール自体の使用を終了するか、または残して再利用するかは問いません。できればコメントにスレッドプールを残したかどうかを書いてください。

法演算 (Nested Flatten)

ここでいう法演算とは,与えられた数(ここでは「法」と言います)で剰余をとりながら行う計算のことです.たとえば,法が10である場合,以下のように計算します.

  • 足し算
    • 1 + 2 = 3
    • 7 + 3 = 0 (10を10で割った余りは0)
    • 11 + 12 = 1 + 2 = 3
  • 引き算
    • 3 - 2 = 1
    • 2 - 3 = 9
  • 掛け算
    • 2 * 3 = 6
    • 11 * 12 = 1 * 2 = 2
    • 18 * 39 = 8 * 9 = 2

式と法を与えたときに,このような法演算を行い,計算結果を表示するプログラムを作成してください.

注意点

  • プログラムの入力には,式と法が与えられます.
    • 式に現れる数は,整数のみと仮定してかまいません.しかし,法より大きな数が与えられるかもしれませんし,負の数が与えられるかもしれません.
    • 法は2以上の正整数のみが与えられます.
    • 式と法は,プログラムにとって都合のよい形式で与えられると仮定してかまいません.ソースコード中に埋め込んでしまってもかまいません.
  • 足し算,引き算,掛け算に対応してください.
    • 法10の世界においては,1 - 2 と 1 + 8 は同じ意味です.引き算の計算においては,この性質を使い,足し算に変換してから計算してもかまいません.
  • プログラムの出力として,計算結果を表示して下さい.

  • 与えられた式の中に,範囲外の数(負の数や,法の数以上の数)が現れた時には,必ず一度,式全体を正規化し,その結果を表示してから計算を行って下さい.
    • ここでいう「正規化」とは,式の中のすべての項をいったん法で剰余をとり,0以上,法-1以下の範囲になるようにする,ということです
    • 正規化をする際に,引き算を足し算へ変換する処理を一緒に行ってもかまいません.
    • 計算過程で範囲外の数が現れたときには,正規化を行うことが望ましいですが,必ずしも行う必要はありません.(最終的な計算結果が正しければよしとします)
Meertens数 (Nested Flatten)

お題#100「正整数のゲーデル数化?」で定義した goedel を適用すると自分自身になるような数,すなわち goedel (n) == n となるような正整数 n を見つける関数を定義してください.

このような数のことをMeertens数と言うそうです.

32bitsの符号なし整数(あるいは10進10桁整数)までの範囲で探すのにどのくらい計算時間がかかったかをCPUのスペックとともに教えてください.また,その実装で64bit符号なし整数(あるいは10進20桁整数)までの範囲で探すのにどのくらい計算時間がかかりそうか見積ってください(もちろん実際に計算して計算時間を示していただくのでもかまいません).

魔方分割数 (Nested Flatten)
1 .. N^2までの数をN個の数字の和が等しいN個のグループに分けたいと思います。

たとえば、N=3のときは、
(1) { 1, 5, 9 }, { 2, 6, 7 }, { 3, 4, 8 } 
(2) { 1, 6, 8 }, { 2, 4, 9 }, { 3, 5, 7 }
の2通りの方法があります。

ここで指定されたNに対して、何通りのグループ分けの方法があるかを数えるプログラムを作ってください。
(何通りかという値だけが出力されればよいのですが、予め計算してある結果を返すのはダメですよ。)
また、N=5を指定したときの実行時間もあわせて教えてください。

なお、数え上げるときの注意として、

・{ 1, 5, 9 } と { 1, 9, 5 }は同じもの

・{ 1, 5, 9 }, { 2, 6, 7 }, { 3, 4, 8 }と
 { 1, 5, 9 }, { 3, 4, 8 }, { 2, 6, 7 }は同じもの
とすることに注意してください。
最大公約数(除算禁止) (Nested Flatten)

あなたが使っている言語で除算と剰余が使えなくなりました。

以下の条件のもと最大公約数を求めるプログラムを書いてください。

条件

  • 除算および剰余の使用禁止
  • 加算や乗算から除算・剰余を単純に定義することも禁止とする
  • ただし, ビットシフトが面倒な場合には引数を2で割った商を返す関数を実装しても構わない
  • 多倍長演算をサポートすること(各言語のライブラリ状況を見たいので)
  • 引数は2つの正整数と仮定して構わない
  • F_1=1, F_2=1のフィボナッチ数列で2000番目と1999番目の最大公約数を求めたときのループ回数を教えてください
自然数の分割(別表現) (Nested Flatten)
正整数の分割といったとき,同じ組み合わせのもの同じ分割とみなし,
0 を除いて降順に並べたものを指すことも多いのではないかと思います.

たとえば,

partitions 1  ⇒ [[1]]
partitions 2  ⇒ [[2],[1,1]]
partitions 3  ⇒ [[3],[2,1],[1,1,1]]
partitions 4  ⇒ [[4],[3,1],[2,2],[2,1,1],[1,1,1,1]]
partitions 5  ⇒ [[5],[4,1],[3,2],[3,1,1],[2,2,1],[2,1,1,1],[1,1,1,1,1]]
partitions 6  ⇒ [[6],[5,1],[4,2],[3,3],[4,1,1],[3,2,1],[2,2,2],[3,1,1,1]
                 ,[2,2,1,1],[2,1,1,1,1],[1,1,1,1,1,1]]

すなわち,

- 1つの分割は非増加列
- 分割は長さが短いものが先
- 同じ長さの分割では辞書順で大きいものが先

という規則でならべたものです.一つの分割に一つのヤング図形が対応します.
たとえば、5 の分割に対応するヤング図形を列挙すると以下 7 つのようになります.

□□□□□
               
□□□□
□

□□□
□□

□□□
□
□

□□
□□
□

□□
□
□
□

□
□
□
□
□

お題:
正整数を与えられたとき上の意味での分割に対応するヤング図形をすべて
標準出力に印字する関数 young を定義してください.ヤング図形の出力は
上の例のように文字'□'を並べてください.

young 50 の出力をファイルにリダイレクトしたときの処理時間はどの程度
かかったかもCPUスペックとあわせt教えてください.
printfの自作 (Nested Flatten)
printf関数を自作してください。
printfの説明は不要だと思います。とりあえずWikiPediaのリンクをはっておきます。

実際にはsprintf関数を作ってください。
注意事項
  • 標準でついているprintf系関数の使用禁止
  • 標準でついているライブラリ以外の使用禁止
  • 引数・返り値等の仕様はできるだけ似せればよい

可変長引数など、言語によっては難しい/不可能な仕様もありますが、いろいろ工夫して本物に近づくようにしてみてください。
1
2
3
4
5
6
7
#include <string.h>

// なにもフォーマットしてない
int mysprintf(char *str, const char *format, ... ){
    strcpy(str, format);
    return strlen(str);
}
文字列リストをTRIE Optimizeされた正規表現に (Nested Flatten)

これは、実例を見た方が簡単だと思います。 CPANにRegexp::Assembleというモジュールがあるのですが、要はこれの簡易版を作って欲しいということです。私自身、同様のことを行うモジュールを過去にいくつか作っています(e.g Regexp::Optimizer)。

ここでは、文字列のリストを受け取って、それをTRIE化した正規表現に出来ればOKです。Regexp::AssembleやRegexp::Optimizerは正規表現を受け取ってそれをTrie化することも可能ですし、Perl 5.10では内部的にTrie Optimizationを行ったりするのですが、そこまでの機能は求めません。

なお、ここで言う「正規表現」は、必ずしもPerl互換のものである必要はありません。それがTrieになっていることをきちんと示せればOKです。

とはいうものの、Perl5互換になっていた方が、サポートしている環境が多くて有用性は高そうです。可能であればそうして下さい。

Dan the Regexp Assembler

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/local/bin/perl
use strict;
use warnings;
use Regexp::Assemble;

my $ra = Regexp::Assemble->new;
while(<>){
    chomp;
    next unless $_;
    $ra->add($_);
}
print $ra->re, "\n"
__END__

% grep program /usr/share/dict/words 
program
programist
programistic
programma
programmar
programmatic
programmatically
programmatist
programmer

% grep program /usr/share/dict/words | perl sample.pl 
(?-xism:program(?:m(?:a(?:ti(?:c(?:ally)?|st)|r)?|er)|ist(?:ic)?)?)
BFコンパイラー (Nested Flatten)

「どう書く?」でまだ出ていないのが不思議なお題。それがBF処理系。 ここでは、BFで書かれたソースを、同じ言語に変換するコンパイラーを募集します。

私自身、すでにPerlとJavaScriptに関しては http://blog.livedoor.jp/dankogai/archives/50545151.html でやっているのですが、他の言語バージョンも是非見たいので。

Dan the Brainf.ucker

水の移し替えパズル (Nested Flatten)

A, B, Cの容器があり,それぞれ水が4L, 2L, 10L入っている. ここで次の操作を繰り返す.

(*)「A, B, Cのどれか二つの容器から水を1Lずつくみ上げ,残りの容器に移す.」

たとえばA, Bから1Lずつくみ上げて移せばA=3L, B=1L, C=12Lとなる. くみ上げる前の容器には必ず水が入っているとする.

(*)を繰り返してどれか一つの容器にのみ水がはいっている状態にする最小手数を求めよ.

可能ならA=827392L,B=65536L,C=122880Lのときも求めよ.


このお題は光成さんの投稿を元に作成しました。ご協力ありがとうございます。

文字列の反転(括弧の対応を保存) (Nested Flatten)
与えられた文字列を前後反転する関数 reverseString2 を書いてください。
ただし、reverseString2 は単純に文字列を反転するのではなく、括弧の対応
を保存するようにしてください。

以前のお題で作成した単純に与えられた文字列を単純に前後反転したもの返す
reverseString では

  reverseString("文字列(もじれつ)の反転(はんてん)") 
    → ")んてんは(転反の)つれじも(列字文"

のように括弧の対応は保存されませんが、reverseString2 では

  reverseString2("文字列(もじれつ)の反転(はんてん)")
    → "(んてんは)転反の(つれじも)列字文"

のように括弧の対応が保存されます。
括弧文字は、'('と')'、'{'と'}'、'['と']'で、それぞれASCII文字と仮定し
てください。

  reverseString2("対応[の{とれている(さまざまな)括弧}の(例)]です。")
    → "。すで[(例)の{弧括(なまざまさ)るいてれと}の]応対"

入力文字列では対応の取れている括弧の内側には対応の取れない括弧文字はな
いと解釈してください。たとえば、

  reverseString2("これ(は(対応のとれていない)括弧がある例です。")
    → "。すで例るあが弧括(いないてれとの応対)は(れこ"

次のような場合は対応のとれている括弧はないという解釈になります。

  reverseString2("これ(も{対応の)とれていない}括弧の例です")
    → "。すで例の弧括}いないてれと)の応対{も(れこ"

日本語対応にする場合の文字のエンコーディングは実装側で都合のよいように
仮定してください。日本語対応であることは望ましいですが、必須ではありま
せん。 

---
このお題はnobsunさんに投稿いただきました。ご協力ありがとうございます。
ソートするコードの生成 (Nested Flatten)
Meta-Loopless Sortsの改題です.

n個の整数をソートするプログラムを生成するプログラム gensort を 書いて下さい.条件は以下のとおり

  1. 生成するプログラム,生成されたプログラムは同じ言語にして下さい.
  2. 生成したプログラムはファイルに書き込んでください.
  3. 生成されたプログラムでは最初に n 個の整数を読み込んで, n個の変数を初期化してください.「可能なら」変数名は,アルファベット 一文字で a,b,c ... の順で使ってください.n = 5 なら 変数は a, b, c, d, e です.
  4. 生成されたプログラムでは,if 文あるいは if 式で2つの変数を比較して いって,変数の順が確定したら,その順で変数の値を出力するようにして 下さい.
  5. 生成される側のプログラムでのアルゴリズムやデータ構造を工夫する問題では ありません :)

gensort 3 で生成した Pascal のプログラム例は以下のとおりです.

program sort(input,output);
var
a,b,c : integer;
begin
  readln(a,b,c);
  if a < b then
    if b < c then
      writeln(a,b,c)
    else if a < c then
      writeln(a,c,b)
    else
      writeln(c,a,b)
  else
    if a < c then
      writeln(b,a,c)
    else if b < c then
      writeln(b,c,a)
    else
      writeln(c,b,a)
end.

n の値を 2 〜 10 くらいまで変化させて以下の処理時間を測定してください.

1. gensort n の処理
2. 生成したプログラムの処理
   2-1. コンパイル言語の場合は,コンパイル時間と実行時間
   2-2. インタプリタ言語の場合,可能ならロード時間と実行時間を別測定,
        分解できないなら実行時間
ごさっしのとおり,出力されたプログラムは n の値で急激に大きくなります. n が大きいと gensort n で文法的に正しいプログラムは生成できてもコンパ イル や実行ができないということもありえると思います.処理系ごとの限界がわか ると面白いのではないかと思います.オリジナルの問題は Pascal のプログラム コードを生成するプログラムを書けという問題でしたが,生成する側とされる側 の言語を同じにするほうが面白いですよね.
この問題はnobsunさんからの投稿です。ご投稿ありがとうございました。助かります。
exp(pi * sqrt(n))が整数に近くなるnを探す (Nested Flatten)
1以上200未満の整数nのうち、 exp(pi * sqrt(n))がほとんど整数であるようなnを求めるコードを書いてください。 なお、expは底がeである指数関数 - Wikipedia、 piは円周率、sqrtは平方根です。また「ほとんど整数である」とは 整数からプラスマイナス0.0001の範囲にあることとします。

Pythonで34行のスクリプトを書いて得られた出力の例が下のようになります。

37 199148647.999978
58 24591257752.000000
67 147197952743.999999
163 262537412640768744.000000 
この問題は光成さんに教えて頂いた e^{π*sqrt{163}}≒26253741640768744 が元になっています。ご協力ありがとうございました。
音声合成でHello, world! (Nested Flatten)
与えられた文字列を音声合成して再生する関数を作ってください。

使用したライブラリはタグでつけてください。またOSに依存する場合もタグでつけてください。日本語文字列も発音できることが好ましいですが、必須ではありません。

以下はサンプルです。

>>> say("Hello, world!")
>>> say("con nitch were") # 「こんにちは」
>>> say("daw cat coo org, sole what program mar know tum yen know Colosseum death")
PageRankの計算 (Nested Flatten)
ページランク - Wikipediaを求めるプログラムを作ってください。(PageRankはGoogleの商標です)

詳しい導出方法はGoogle の秘密 - PageRank 徹底解説の3章に載っていますが、 簡単に説明すると

  1. ページがn枚ある場合、n×nの2次元配列を用意する。
  2. ページiからページjにリンクがある場合、mat[j][i] = 1 / num_link[i]とする。ただしnum_link[i]はi番目のページから出ているリンクの総数。
  3. 行列計算ライブラリを使ってできあがった2次元配列の固有値、固有ベクトルを求める。
  4. 出力された固有ベクトルから合計が1になるようなPageRankを算出する

という流れになります。

Pythonで表現すると下のようになります。 ?????の部分は空行を入れて10行でしたので 何百行ものコードになってしまった場合は きっとお題の趣旨から外れていると思います。 このお題の趣旨は「行列計算ライブラリを使って」PageRankを計算することなので、 自力で固有値の計算を実装することは求められていません。

data = {
    1: [2, 3, 4, 5, 7],
    2: [1],
    3: [1, 2],
    4: [2, 3, 5],
    5: [1, 3, 4, 6],
    6: [1, 5],
    7: [5],
}

?????

print pagerank
# [0.303514376997, 0.166134185304, 0.140575079872,
#  0.105431309904, 0.178913738019, 0.0447284345048,
#  0.0607028753994]
このお題はところてんさんの「行列演算系のお題が欲しい」という要望を元に考えたものです。ありがとうございました。
Tiny MML (Nested Flatten)
文字列の入力をとり、音を鳴らすプログラムを作ってください。

入力はcがド、dがレ、eがミ、fがファ、gがソ、aがラ、bがシ、rが休符とします。この8文字以外の文字は入力に含まれていないと仮定して構いません。おのおのの音符・休符は八分音符・八分休符とします。

オクターブや音の長さの変更、同時発音などの機能は不要です。

サンプル入力(カエルの歌)

cdefedcrefgagfercrcrcrcrcdefedcr
入出力の中継 (Nested Flatten)
以下のようなプログラムを作ってください。
  • コマンドライン引数を二つ取り、引数で指定されたプログラムを起動する(以下A, B)
  • Aの標準出力をBの標準入力へ、Bの標準出力をAの標準入力へ中継する。
  • A, Bどちらかが終了した場合はもう片方を終了して自身も終了する。
ウィンドウの表示 (Nested Flatten)
画面中央に幅100ピクセル、高さ75ピクセルのウィンドウを表示してください。
タイトルには「こんにちは、GUI!」と表示してください。

使用するGUIライブラリに名前が付いているならば、それをタグでつけてください。(例えば「Swing」など。)

追記:100x75はあまりに小さすぎるようなので、小さすぎるせいでうまく行かない場合は400x300でもいいということにします。 このお題の意図は「小さいウィンドウを出せ」というわけではないので。

Index

Feed

Other

Link

Pathtraq

loading...