アルゴリズムを勉強してこなかったツケを30歳直前にして払う

Javaでビジネスアプリ開発なんてことを仕事にしているとアルゴリズムを書く力が必要になる場面は少ない。データ構造や細部のアルゴリズムはほとんどオブジェクトとして抽象化されてるし、データ操作は単純なプロパティの出し入れだけだったりするので手続き大部分がネストもしない単純なループ。8年もそんなことやってると「技術=クラス&テーブル設計」ってことになり、コードを書く力を全然鍛えないままここまでやってきた。
このままではコード書きとして胸を張れないことはわかっているので、ふつける読んだりRubyやったりSICP読んだり(どれも途中)してみたが今一つ自信が持てない。結局のところこの不安はメモリ上にあるデータを直接扱う知識が身についてないことから来ていると気付いてからはあちこち言語をつまみ食いするのをやめた。結局のところCができなきゃ何やったって別の檻に入るだけだ。というわけで、

  1. 言語の勉強はしばらくSICPK&Rだけに絞ろう。
  2. K&Rを通勤時間に一通り読み、ポインタや構造体まで理解
  3. さて休日に演習問題やってみよう
  4. 1章「やさしい入門」最後の演習でクソ悩む。 <- ようやく今ココ抜けた

StringクラスのメソッドとかPerlとか正規表現があったから今まで文字列処理なんてやったことなかったけど、走査しないと終端すらわからない単なるchar配列は何もサービスしちゃくれない。演習たった5つ解くのに何時間悩んだことか。「オブジェクト指向開発に社内でいちばん詳しいS本先生」なんて言われてても実際こんなもんですよ。こんなんでS本先生きこのれるのか凄く不安だね。そしてこんなのまだまだFizzBuzzなハズ。
しかし面白い。これに比べたらJavaのなんと眠たいこと。
とりあえず汚ないソース貼っておくか。か...勘違いしないでよ!!ポインタ使ってないのは1章ではまだ出てきてないだけで、後で書き直しに戻ってくるんだからねっ!!
40になろうが50になろうが立派なプログラマになってやる。あきらめねーよ?

プログラミング言語C 第2版 ANSI規格準拠

プログラミング言語C 第2版 ANSI規格準拠

/* entab: 演習 1-21 空白をタブに置換 */
void entab(char to[], char from[], int tabstop)
{
    int i, j, spc;
    char c;
    for (i = j = spc = 0; c = from[i]; ++i) {
        if (spc > 1 && i % tabstop == 0) {
            to[j++] = '\t';
            spc = 0;
        }

        if (c == ' ')
            ++spc;                /* push space */
        else {
            for (;spc > 0; --spc) /* flush spaces */
                to[j++] = ' ';
            to[j++] = c;
        }
    }
    to[j] = '\0';
}

/* wrap: 演習 1-22: 指定文字数(ブランク以外)で折り返し */
void wrap(char to[], char from[], int tabstop, int wrap)
{
    int i, j, spc;
    char c;
    for (i = j = spc = 0; c = from[i]; ++i) {
        if (j > 0 && j % wrap == 0)
            to[j++] = '\n';

        if (c == ' ')
            ++spc;
        else if (c == '\t')
            spc += tabstop;
        else {
            for (;spc > 0; spc--)
                to[j++] = ' '; /* flush spaces & detabbed tabs */

            to[j++] = c;
        }
    }
    to[j] = '\0';
}

/* ignorecomment: 演習 1-23 コメントを除去 */
void ignorecomment(char to[], char from[])
{
    int i, j, comment = 0, quot = 0;
    char c;
    for (i = j = 0; from[i]; ++i) {
        if (!comment && from[i] == '"')
            quot = quot ? 0 : 1;
        else if (!quot && !comment
                 && from[i] == '/' && from[i + 1] == '*')
            comment = 1;
        else if (!quot && comment
                 && from[i] == '*' && from[i + 1] == '/') {
            i += 2;
            comment = 0;
        }

        if (!comment)
            to[j++] = from[i];
    }
    to[j] = '\0';
}

/* parseparen: 演習 1-24 括弧や引用符の整合性を検査
   ''の対応はサボり。*/
int parseparen(char str[])
{
    int i, j, quot = 0, comment = 0;
    char c, stack[MAXLINE];
    for (i = 0; i < MAXLINE; ++i)
        stack[i] = ' ';

    for (i = j = 0; c = str[i]; ++i)
        if (!comment && c == '"')
            quot = quot ? 0 : 1;
        else if (!quot && !comment
                 && c == '/' && str[++i] == '*')
            comment = 1;
        else if (!quot && comment
                 && c == '*' && str[++i] == '/')
            comment = 0;
        else if (!quot && !comment)
            if (c == '{')
                stack[++j] = '}';
            else if (c == '(')
                stack[++j] = ')';
            else if (c == '[')
                stack[++j] = ']';
            else if (c == '}' || c == ')' || c == ']')
                if (j == 0)
                    return -1;
                else if (c != stack[j--])
                    return -j;
    return -j;
}