SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|12|

2024-12-06(Fri) 自分を見詰め、字を詰める

  ここしばらく、Factorioに夢中なのだが、仕事の方でも実にエキサイティングである。一部の勢力からの自分の評価が極めて低いことを知ってしまったのである。

  しかし、一時的には腹が立ったものの、しばらくして、その勢力からの評価が低いことは、むしろ望ましいことなのではないかということに気づいてしまった。その勢力の考え方は、決して自分の信念と相容れないからだ。一方で、自分が好きな人、尊敬する人たちからは変わらず手放しでの高評価を受け続けているのだし、まぁ、それでいいかと。

  自分としては、マズローの4段階目「承認の欲求」で自身について納得しつつ、5段階目「自己実現の欲求」を半ば達成しつつあるような心境だ。乱れた心も整いつつあるのを感じる。

  考えてみれば、生殺与奪の権利を持っているのはこっちなのだ。金もあるし。それで自ら好きな仕事だけしてればいい立場になったのだから、それが一部からの低評価との引き換えだとしても別にいいやと。自分の信念に背くような仕事の仕方すんの、ヤだしね。それさえ無理なら、袂を分かつさ。

  なんだかキャプテンハーロックの気持ちってこうだったのかもと思えてきた。どんな大勢力が相手だろうと、俺の旗の下に、俺は自由に生きる。それがアルカディア。それが男。それでいい。

  そんなこんなで、片や落胆しつつ、いつも以上に楽しんで仕事をしているのだが、その中で「字詰め」処理を行う必要が生じてしまった。Rubyで。長い一文を、例えば18文字、で折り返す処理である。これが意外と難しい。え!? そんなん、1行じゃん?

print(target.gsub(/(.{18})/, "\\1\n"))

  ……って思うかもしれんが、それは甘い。

 その話をカミさんにしたら、そんなの
借りときゃいいのに、という反応。いや
、そりゃそうだけど、2km弱を乗った
ところで何になるってんだ、などといい
つつ、なぜかRotary-EVの素晴
らしさについて語りだしてしまうオレw
。ほとんど乗らないワシらにはオーバー
 :

  まず、英文字と漢字とは幅が違うので、同じ1文字と数えると右端が揃わない。それよりなにより「禁則処理」がなされない。句点(。)や読点(、)が行頭に位置してしまっている。そんなの気にしないという向きもあろうが、自分はイヤだ。そんな処理もできないのかと思われるのは恥ずかしい。

  しかし、これが意外と難しい。組版するわけではないので、次行への追い出しのみの実装でよいのだが、先頭から処理していくと、遡るような処理が必要になるのだ。例えば、

「その時、彼は『こんにちは(笑)。』と書き込んだの。」

  を、18文字で詰めると、

「その時、彼は『こんにちは(笑)。』
と書き込んだの。」

  だが、17文字で詰めると、

「その時、彼は『こんにちは
(笑)。』と書き込んだの。」

  1文字でなく、5文字も減らす必要が生じるのだ。

  こんな典型的な処理、どこかで誰かが書いているだろう、と思って検索してみたが、良いものが見つからない。思い返せば、彼の「電脳倶楽部」の創刊号で祝一平編集長自らがPDSとしてCで書いて公開した「wrap.x」がまさにそれなのだが、コードを入手する手段がない。当時はまるで興味をそそられなかったプログラムだったが、ディスクマガジン用のリーダを書こうと思えば、そら一番に必要になるコードだよなぁ。いまさらに深く納得。

  それなりにうんうん唸って、何度か書き直して、そこそこ納得できるコードが書けたが、丸一日かかってしまった。正規表現とかを駆使すればもっとシンプルかもしれないが、そう得意ではないし、ハナモゲるのがイヤなので、使っていない。

class String
 
    def char_wide
        self.getbyte(0) < 0xE0 ? 1 : 2                          # 文字の表示幅を返す
    end
 
    def each_wline(w_max)
        loop {
            c_max = 0; w = 0; self.each_char {|c|               # 仮分割位置を算出する
                w + c.char_wide > w_max and break
                c_max += 1; w += c.char_wide
                c == "\n" and break
            }
            if(self.size > c_max)                               # 1 行分を適切に切り出す
                c = c_max.times {|cr|
                    # 行末禁則文字
                    '([{「『([{'\
                        .include?(self[c_max - cr - 1, 1]) and next     # 仮分割位置の直前(行末)の文字
                    # 行頭禁則文字
                    '),.]}、。」』っッー)]}'\
                        .include?(self[c_max - cr, 1]) and next         # 仮分割位置の直後(行頭)の文字
                    break(c_max - cr)
                }
                yield(self.slice!(0, c))
            else                                                # 残りを返す
                yield(self)
                break
            end
        }
    end
end
 
target.each_wline(38) {|l|
    puts("\t|%s|" % l)
}

  結果はこう。

	| その話をカミさんにしたら、そんなの借|
	|りときゃいいのに、という反応。いや、そ|
	|りゃそうだけど、2km弱を乗ったところで|
	|何になるってんだ、などといいつつ、なぜ|
	|かRotary-EVの素晴らしさについて語りだ|
	|してしまうオレw。ほとんど乗らないワシ|
	|らにはオーバースペックすぎるんだって、|
	|なんていいながら、サイトで見積もりまで|
	|してしまう。天井が黒くって、ロードス|
	|ターとお揃いじゃん。並べたらいい感じじ|
	|ゃない? ……って、そらそうだけど、ホ|
	|ラ、500万だってよ。500万ってさ、1年を|
	|働いてようやく余るかっていう金額だよ。|
	|MX-30のために1年働くって思ったら……い|
	|や、そういうのも意外と悪くないんじゃな|
	|いかw。オレ、チョロいなぁ……。
|
	| 前にも言ったが、代車を貸すほど効率的|
	|なプロモーションはないよなぁ。あー、|
	|やっぱり借りて、明日の仕事はブッチして|
	|しまうべきだったなぁ。人生で最高レベル|
	|の失敗をしたかもしれん……。
|

  関数名の「each_wline」の「w」は「wrap.x」へのリスペクトである。

  書いていて気づいたのだが、既に「半角、全角」という世ではないこともあって、ネット上にコードが見つからないのかもしれない。プロポーショナルな環境の場合、自分で詰めるべきではなく、CSSなどを使うべきなのだろう。

  ついでに、コードを書いたあと、思いついてChatGPTにコードを書かせてみたが、なぜか行頭禁則しか扱ってないし、動かしても何の処理もされなかった。やはり元となるようなサンプルコードがある場合限定なのかもしれん。

  あ、ちな、上記のコードには、一部の禁則文字しか定義していないし、分離禁止文字も実装していない。あしからず。