Language detail: JavaScript - 's unsolved challenges

年賀はがきの当せん番号 (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)

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

(前) 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)
シードを固定した疑似乱数を出力してください。
数回実行して、常に同じ結果が出力されることを確認してください。
メソッド数の多い組み込みクラスを列挙 (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)

 与えた文章の各単語の最初と最後の文字以外の文字を入れ替えた文章を出力する処理を実装して下さい。元の文章の与え方は特に問いません。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#! c:\ruby\bin\ruby.exe -Ks

class Cmabrigde
    def self.convert(word)
        cs = word.split("")
        (cs.size <= 3) ? word : cs.first + cs[1..-2].sort_by { |c| rand }.join("") + cs.last
    end
end

source = <<EOS
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
EOS
source.each_line do |line|
    puts line.chomp.split(/\s+/).map { |word| Cmabrigde.convert(word) }.join(" ")
end
例外処理 (Nested Flatten)

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

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

ACLの制御 (Nested Flatten)
通常、作成者以外は、読み書きができないファイルを新規作成してください。
# UNIX的にいうと「0600」のファイルです。

すでに存在していた場合、新しい内容で上書きしてください。

symlinkアタック等を考慮する必要はありません。

余裕のある人はファイルがすでに存在していた場合、
パーミッションを変更してみてください。
ナイツ関数(ボケの方) (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 考えられる刻子のパターン:
        刻子を手牌から抜く
        手牌が順子の和となっていれば、和了形として抜ける
        刻子を手牌へ戻す
    対子を手牌へ戻す
ここに到達していれば、和了形ではない
ナベアツ算 (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日単位とします

このお題は、以前仕事で作った機能のほんの一部を抜き出して単純化してみました。
プロジェクト管理等でよくあるグラフですね。
IPv6アドレスの短縮 (Nested Flatten)
いろんなところでIPv6の実用化やそれに向けた実験が進められており、今後IPv6のアドレスを見かけることも多くなりそうなので少し触れてみよう、というお題です。

IPv6アドレスは16進表記した2バイトを、コロンで8つつなげて表記します。
例)1230:5670:0000:0000:0123:0000:0000:00ab 

各部分の頭の0は省略できます。上の例はこうなります。
例)1230:5670:0:0:123:0:0:ab 

また、0 が複数続くところは 「::」に置き換えることができます。(ただしアドレス内で1箇所のみ)
例)1230:5670::123:0:0:ab 

この短縮を行う関数を作ってください。
余力のある方は逆変換(伸長)も考えてみてください。
この程度ならライブラリに備わってるかも??
1
2
3
4
5
> ipv6_compress( '1230:5670:0000:0000:0123:0000:0000:00ab' )
1230:5670::123:0:0:ab

> ipv6_compress( '0000:0000:0000:0000:0000:0000:0000:0001' )
::1
データの圧縮と展開 (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)
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)

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

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

漢字の九九に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)
いわゆる、コマンドライン引数の取得(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
echoクライアント (Nested Flatten)

TCPのechoクライアントを書いてください。

  • サーバのホスト名ないしIPアドレス、およびポートはコマンドライン引数で指定します。
  • 標準入力からユーザの入力を受け取り、echoサーバに送信します。
  • echoサーバから受信したデータを標準出力に出力します。

Windowsなら、Simple TCP/IP Servicesを起動してやれば、ローカルの確認用echo サーバとして使えます。

my_program localhost 7 < input_file > result_file

のようにしてリダイレクトを行った場合にも、result_fileがinput_fileの内容と一致するようにしてみてください。

tailの実装 (Nested Flatten)

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

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

最低限必要な機能は、

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

です。

lessの実装 (Nested Flatten)

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

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

最低限必要な機能は、

  • 上下スクロール
  • 検索

です。

コード圧縮 (Nested Flatten)
スペースやインデントなど、本来は必要なく開発効率を上げるために記述が許可されている項目について、
それらを可能な限り減らし、コードを短くするコード書いてください。
また、投稿時に対象とする言語と、実際の処理結果を記載できるとわかり易いかと思います。

以下詳細
・全てを行う必要はありません、どこまで行うかは任意です。
・ローカル宣言など、消しても動作に関係のない構文の削除や置き換えを行っても構いません。
・必ず同じ入力に同じ結果が返るのであれば処理内容を変えることもかまいませんが、推奨・強制はしません。
・コンパイラや実行環境に依存する圧縮は避けてください。
設定ファイルから値を取得 (Nested Flatten)
設定ファイルから項目名をキーとして値を取得するコードを書いてください。
設定ファイルのイメージも載せてください。

ここで設定ファイルとは、
 ・項目名と値のペアが書いてあるファイル
 ・フォーマットはその言語で扱いやすいものでよい
 ・コードと分離され、コードに影響を与えずに変更が可能
を条件とします。ファイルが難しければ同等のものでもかまいません(テーブル、環境変数など)。

例)
----
ファイル:ShowPrice.ini
ITEM_NAME=りんご
ITEM_COST=200

> showPrice()
「りんご」は210円(税込み)
----
ITEM_NAME=みかん
ITEM_COST=100

> showPrice()
「みかん」は105円(税込み)
コメントの削除 (Nested Flatten)
ソースコードからコメント部分を削除するプログラム decomment を書いてください.
すくなくとも,decomment を記述したのと同じ言語で書かれているソースコードが
扱えるようにしてください.



循環関数 (Nested Flatten)
整数nを与えると 範囲lowからhigh内での位置を返すmodular関数を作ってください。
(
  low <high かつ n=0のとき low を返す

    n = 1 のとき low + 1 を返す。
    n = high - lowのときhighを返す。
    n = high - low  + 1 のときlowを返す。
       (循環 : 例* を参考にしてください) 
    n = high - low  + 2 のときlow+1を返す。


    n = 整数 * (high - low)  + 1 のときlowを返す。
    n = 整数 * (high - low) のときhighを返す。
    n = 整数 * (high - low)  + 2 のときlow+1を返す。
....循環の繰り返し
)


例
  modular(n,low,high) -> 出力

  modular(0,100,200)    -> 100

  modular(50,100,200)   -> 150
  modular(100,100,200)  -> 200

  *例
  modular(101,100,200)  -> 100
  
  modular(-1,100,200)   -> 200
  modular(1,-5,200)     ->  -4
  modular(-500,-5,-1)   ->  -5
マルバツゲーム:賢いプレイヤー (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)

固定長のデータが記載されたファイルを読み込むプログラムを作成してください。読み込んだデータは、複数の値を格納できるデータ型に格納してください。

ファイルには、すべて ascii 文字で以下のデータが格納されています。デリミタはなく、固定長で格納されています。レコードとレコードのあいだも改行はありません。

  1. 姓 (12文字) 文字数が足りない場合は、後ろを空白で埋めてあります。
  2. 名 (12文字) 文字数が足りない場合は、後ろを空白で埋めてあります。
  3. 性別 (F,M,Uの3種類、1文字)
  4. 年齢 (3桁の数字、桁数が足りない場合は、ゼロで埋めず、頭を空白で埋めてあります。
  5. 年 2008 固定
  6. 月 03 固定
  7. さらに以下のデータが日付分くりかえされます。
    1. 日付 (01 〜 31) 2文字
    2. 朝食のメニュー (500文字)
    3. 昼食のメニュー (500文字)
    4. 夕食のメニュー (500文字)

以上の形式のデータ500人分を読みこんで、データを複数の値を格納できるデータ型に格納してください。データに大して何か処理を行う必要はなく、すぐに破棄してかまいません。

この問題は、このようなファイルをどのように扱うかを知りたくて作成しました。

不動点演算子 (Nested Flatten)

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

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

必ず解ける迷路 (Nested Flatten)
以下のルールを満たすn×mの迷路を出力するプログラムを作ってください。

1. 格子状の迷路であること。
2. 経路の幅は均等であること。
3. 迷路のある地点からの全ての地点に到達する経路が1つだけ存在すること。
   ループも認めません。
4. 出力の度にランダムな迷路であること。
   ランダムシードが同じ時に同じ迷路になってしまうのはよいです。

たとえば、n=4, m=5の迷路の出力は以下のようになります。

 |1|2|3|4|
―■■■■■■■■■
1■   ■   ■
―■■■ ■■■ ■
2■   ■   ■
―■ ■■■ ■ ■
3■     ■ ■
―■ ■■■ ■ ■
4■ ■   ■ ■
―■ ■ ■■■ ■
5■ ■   ■ ■
―■■■■■■■■■

こう言うのは、×の部分が3のルールに違反するのでダメです。
 |1|2|3|4|
―■■■■■■■■■
1■   ■×■ ■
―■■■ ■■■ ■
2■   ■   ■
―■ ■■■ ■ ■
3■     ■ ■
―■ ■■■■■ ■
4■ ■×××■ ■
―■ ■×■■■ ■
5■ ■×××■ ■
―■■■■■■■■■

このようなループも2のルールに違反するのでダメです。
 |1|2|3|4|
―■■■■■■■■■
1■     ■ ■
―■■■ ■ ■ ■
2■   ■   ■
―■ ■■■ ■ ■
3■     ■ ■
―■ ■■■ ■ ■
4■ ■   ■ ■
―■ ■ ■■■ ■
5■     ■ ■
―■■■■■■■■■

できたプログラムを使って n=1024, m=1024 の迷路を作るのにかかった時間を教えてください。


難易度高めです。限られたメモリを使って縦方向に無限に広い迷路を
どうやって作るのかを考えると答えが見えてくると思います。
ソースコードはJavaで150行程度になりました。
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番目の最大公約数を求めたときのループ回数を教えてください
文字列リストを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)?)?)
続・ファイル内の重複行削除 (Nested Flatten)

ファイル内の重複行削除(後優先) 」の続編です。

1行あたり平均60文字のデータが書き込まれた、巨大なファイルがあるとします。どのくらい巨大かというと、積んでいるメモリの10倍程度の容量があります。このファイルから、同じ内容が書かれている行を取り除くプログラムを作ってください。ただし、同じ内容が書かれている行のうち、最後に出現したものを残すものとします。

このサイズのファイルを丸ごとメモリに読み込もうとしてしまうと、 スラッシング - Wikipedia が発生することが予想されます。そこで行単位で読み込もう、というのが前回のお題の趣旨でした。

しかし、与えられたファイルが運悪く「一致する部分のないファイル」である可能性を考えてみましょう。たとえ1行ずつ読んで処理をしたとしても、「重複するかどうかの判定」のために前の行をまるごとメモリに取っておいたのでは、最終的にファイルを丸ごとメモリに乗せることになってしまいます。

こういうデータが入力されうる状況の場合にどう書くか、というお題です。前回のお題の条件3「ファイル全体を一度にメモリに読み込んで処理しないこと」を「たとえすべての行が異なるようなデータであっても、メモリの消費量をファイルサイズのおよそ10%程度に抑えること」と読み替えてください。

追記:「メモリの10倍」はさすがに条件として厳しすぎました。「ファイルのサイズは4ギガバイト未満であり、メモリの消費量をファイルサイズの半分以下に抑えること」と読み替えてください。半分以下に抑えられているのならば題意は満たすものとします。もちろん、頑張ってもっと少ないメモリで動くようにするのもアリです。

ソートするコードの生成 (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さんからの投稿です。ご投稿ありがとうございました。助かります。

Index

Feed

Other

Link

Pathtraq

loading...