なんじゃくにっき2

プログラミングの話題中心。たまにゲームの話とか。

言語処理100本ノック UNIXコマンド 10-19

言語処理100本ノックのUNIXコマンド章を解きました。

Pythonでも解くことを想定されているのかもしれないけど、シェルスクリプトでだけ解きました。

シェルスクリプトで出来るから良いかなって思って。

githubに置いておきます。

https://github.com/nanjakkun/nlp_100_ans/tree/main/src/1

言語処理100本ノック 準備運動 00-09

言語処理100本ノックを解いていきます。

言語処理100本ノック 2020 (Rev 2) - NLP100 2020

解くのに使ったプログラミング言語Python 3。

なるべく関数型言語チックに書いているつもりです。再代入はなるたけ避ける。

解答はgithubにも載せておきます。

GitHub - nanjakkun/nlp_100_ans: 言語処理100本ノックの解答

まとめ

1章 準備運動

このエントリです。

2章 UNIXコマンド

https://nanjakkun.hatenablog.jp/entry/2024/03/17/%E8%A8%80%E8%AA%9E%E5%87%A6%E7%90%86100%E6%9C%AC%E3%83%8E%E3%83%83%E3%82%AF_UNIX%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89_10-19

1章 準備運動の解答

00

文字列”stressed”の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.

str = "stressed"[::-1]
print(str)

sliceの使い方を知っていれば一瞬。[start:stop:step]。

他言語から来るとstrにreverseってメソッドが欲しくなるかも。

01

「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.

str = "パタトクカシーー"[::2]
print(str)

これも前問と同様sliceの使い方知ってれば。

02

「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.

itr = map(lambda x: x[0] + x[1], zip("パトカー", "タクシー"))
print("".join(itr))

zip使いましょう。

03

“Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.”という文を単語に分解し, 各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.

import re

str1 = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
itr1 = map(lambda str: len(str), re.split(r'[\s,\.]+', str1))
itr2 = filter(lambda x: x > 0, itr1)
print(list(itr2))

04

"Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.” という文を単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字, それ以外の単語は先頭の2文字を取り出し, 取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.

import re

str1 = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."

def to_elemnt_symbol(itr) -> str:
  idx = itr[0]
  if (idx in [1, 5, 6, 7, 8, 9, 15, 16, 19]):
    return itr[1][0], idx
  else:
    return itr[1][0:2], idx

itr1 = filter(lambda x: len(x) > 0, re.split(r'[\s,\.]+', str1))
itr2 = map(to_elemnt_symbol, enumerate(itr1, 1))

print(dict(itr2))

他言語だとmapWithIndexみたいなのを使うところはPythonではenumerate。

05

与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ. この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ.

def word_n_gram(text, num=2):
  words = text.split(" ")
  return list(map(lambda i: words[i:i+num], range(len(words))))

def char_n_gram(text, num=2):
  words = text.replace(" ", "")
  return list(map(lambda i: words[i:i+num], range(len(words))))

text1 = "I am an NLPer"

print(word_n_gram(text1, 2))
print(char_n_gram(text1, 2))

06

paraparaparadise”と”paragraph”に含まれる文字bi-gramの集合を, それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ. さらに,’se’というbi-gramがXおよびYに含まれるかどうかを調べよ.

# 前回の問題で使ったのと同じ関数
def char_n_gram(text, num=2):
  words = text.replace(" ", "")
  return list(map(lambda i: words[i:i+num], range(len(words))))

text1 = "paraparaparadise"
text2 = "paragraph"

X = set(char_n_gram(text1))
Y = set(char_n_gram(text2))

print("union: ", X | Y)
print("intersect: ", X & Y)
print("diff: ", X - Y)

if "se" in X:
  print("X contains se")

if "se" in Y:
  print("Y contains se")

Set使いましょう。

07

引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ. さらに,x=12, y=”気温”, z=22.4として,実行結果を確認せよ.

def weather(x: int, y: str, z: float) -> str:
  return f'{x}時の{y}は{z}'

print(weather(12, "気温", 22.4))

文字列に変数展開する方法はいくつかあるけどその1つ。

08

与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ. - 英小文字ならば(219 - 文字コード)の文字に置換 - その他の文字はそのまま出力 この関数を用い,英語のメッセージを暗号化・復号化せよ.

def cipher(text: str) -> str:
  def transform_char(ch):
    if (97 < ord(ch) & ord(ch) < 122):
      return chr(219 - ord(ch))
    else:
      return ch

  return "".join(list(map(transform_char, text)))

text1 = "lorem ipsum"
print(cipher(text1))
print(cipher(cipher(text1)))

decodeとencodeが同じ関数なんですねえ。2回同じのを作用させると元に戻る。

09

スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し, それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ. ただし,長さが4以下の単語は並び替えないこととする. 適当な英語の文(例えば”I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .”)を与え, その実行結果を確認せよ.

import random

def typoglycemia(text) -> str:
  def shuffle(word) -> str:
    if (len(word) <= 4):
      return word
    else:
      substr = word[1:-1:]
      return word[0] + "".join(random.sample(substr, len(substr))) + word[-1]

  words = text.split(" ")
  return " ".join(map(shuffle, words))

text1 = "I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
print(typoglycemia(text1))

以前流行ったアレですね。

この ぶんょしう は イリギス の ケブンッリジ だがいく の けゅきんう の けっか 、 にんんげ は もじ を にしんき する とき その さしいょ と さいご の もさじえ あいてっれば じばんゅん は めくちちゃゃ でも ちんゃと よめる という けゅきんう に もづいとて わざと もじの じんばゅん を いかれえて あまりす。

余談

ChatGPT(3.5)に解けるのかと思って問題を与えてみたら、大体解けますね。ちょっと間違ってたりするけど。

と言ってもこれは解答をネットにアップしている人は他にもいるので、まあ、って感じではありますが。

速度的には自分で書くより向こうのほうがずっと速いのでこちらの完敗でございます。

reCAPTCHAとか画像認証をやめてほしい

題意のとおりreCAPTCHAや画像認証をやめてほしい。

Webサービスで何かのステップの先に進もうとすると人力で画像を読み取って入力しないといけないやつね。

読みづらくした文字を読み取って入力させたり、この◎◎枚の絵の中から●が描かれたものを選べ、みたいなやつ。

正直あの手のものが苦手で、何度も失敗することがよくある。

セキュリティを担保するんだったら他段階認証とかにしてほしい。ログインが必要なサービスだったらそっちのほうが安全だし利用者に負担がかからないと思う。

画像認証なんて攻撃者がちょっと本気を出せば突破できるものだし。

ログイン不要でコメントできるサービスでbotを防ぐのには多少効果があるのかはしれない。

VSCodeのextention Ruby LSP

VSCodeRuby用ExtentionとしてはVSCode Ruby を使っていたんですが、Ruby LSPへの乗り換えを勧められるので乗り換えました。

VSCode Ruby - Visual Studio Marketplace

Ruby LSP

Ruby LSP - Visual Studio Marketplace

VSCodeのextention画面からRuby LSPインストールします。

Multi-root workspaces

Ruby LSPをインストールしてもそのままでは動きません。

なんか”Lockfileがプロジェクト直下に見当たらないよ”的なエラーメッセージが出ます。

VSCodeのMulti-root workspacesを有効にしろと言ってきます。

(なお、1 Workspaceに1 root = 1 projectの場合にはそのまま動くと思います)

workspacesをMulti-rootにするには、workspace直下の.code-workspaceを編集します。

{
    "folders": [
        {
            "path": "."
        }
    ],
}

上記のようにrootが直下1つになっているのを

{
    "folders": [
        {
            "path": "project_a"
        },
        {
            "path": "project_b"
        },
    ],
}

のようにします。

気を付ける点

Ruby 3.0以降でないと使えないです。

Ruby 2.7以前のプロジェクトを触らないときは効いてくれません・・

また当然ですがプロジェクトの.ruby-versionで指定されたバージョンと同じバージョンのRubyがローカルに必要です。

dockerで開発しているといなかったりするんですよねえ。

IRBの色を変えたい

なーんかRubyのREPLの色が見づらくて変えられないかなーと思っていたら変えられるとのこと。

reline/doc/reline/face.md at master · ruby/reline · GitHub

$HOME/.irbrc に

if defined? Reline::Face
  Reline::Face.config(:completion_dialog) do |conf|
    conf.define :default, foreground: :white, background: :blue
    conf.define :enhanced, foreground: :white, background: :magenta
    conf.define :scrollbar, foreground: :white, background: :blue
  end
end

relineがない環境でirbが落ちないようにinstallされているか調べています

両手いっぱいに芋の花を 無職クリア

概要

Switchの「両手いっぱいに芋の花を」というゲーム、どんな職の組み合わせでもクリアできるらしい、ということで

何なら無職オンリーのPTでもクリアできるんじゃね?

と思い立ってやってみました。

注:無職なんて職業はこのゲームにありません。技能を取得しなければ全職ステータスが同じ上に装備できるものも同じです。

要は技能取得なしの縛りプレイです。

方針

技能を取得しないのでポイントの割り振りに悩まされることはありません。

戦闘中にできることは通常攻撃、通常ガード、構え直し、の3つのみです。

装備をどうするかが攻略の鍵です。

複数攻撃手段

戦闘中にできることは3つ、と言いましたが装備品によっては装備している間だけ技能が使えるようになるものがあります。

このうち複数攻撃できるものは

  • 雷雨の矛で使えるようになる「連鎖する稲妻」
  • 円鱗の盾で使えるようになる「火炎」

回復手段

回復手段も限られていて

になりますが後ろ2つは終盤まで手に入りません。

とはいえ、このゲームは回復よりガードが重要で、回復がないと勝てなかったと思われる戦いは3つだけでした。

個別攻略

ワーラットの見習い術士

初めての小ボス。流石に余裕です。

ウィザードがいると戦利品の凍てつくワンドがとても役立ちますが技能を使えないので無駄です。分解しましょう。

ミノタウロスの闘士

ここまで同じ敵と複数回戦う稼ぎなし、隠しアイテムなしでやってきましたが早々に負けました。

ちょっとずるして「不敗のカトラス」を回収してきてから再戦します。

溶岩を這うもの

初めての中ボス。意外と初見で楽勝でした。

事前に雷雨の矛を取っておいたのが良かったです。

蛇の王

とてもつらいです。ガードをしてもスタミナが切れて崩されたりちょっとずつ削られて負けたりします。

ここでポーションベルトを使えばよいということに気づきました。崖下の窪地でどう猛無比の一角獣を狩って素材を集めます。 素材をなかなか落としてくれないのでついでにレベルも上がります。

また、スタミナ切れに対処するために赤いスクトゥムでスタミナを増やします。

ポーションを使う精神力もなくなったところでギリギリ撃破。

前衛

  • 不敗のカトラス
  • 赤いスクトゥム
  • 重いグリーヴ

中衛

  • 雷雨の矛
  • 赤いスクトゥム
  • プレートアーマー

後衛

  • 狙撃手の長弓
  • なし
  • レザーアーマー

古都の剛腕

小ボスですが地味につらいです。

野生のクラブ、一撃離脱のウォーハンマー、大陸製の杖 + 杖使いのケープを集めてきてちょっとずつ強化して殴り倒しました。

ここから鉄を使って強化していっているので慢性的に鉄不足です。

要らないアイテムはどんどん分解。

璃々たるグリフィン

3体目の中ボス。

遠距離攻撃しか当たらないので事前に大陸製の弓を2本集めてきて中衛と後衛から攻撃します。

あっさり撃破。

この攻略では必須アイテムの勇壮の革鎧の材料をたまに落とすので落とすまで何度か通いましょう。

倒すのが楽で良かった。

烙印のインプ

広葉樹林の奥地 B3Fにいます。

召喚が厄介・・なんですが数が増えると連鎖する稲妻の威力が上がるので一網打尽。

女王の側仕え x5

広葉樹林の奥地 B2Fにいます。

5体で出てくるのでコイツラも連鎖する稲妻の威力が上がるので一網打尽。

LVが低くて魔力が足りないと生き残ってしまうかもしれません。

この時点でだいぶ防御力の高い寵臣の甲殻鎧の材料を落とします。

マーフォークの難船略奪者

こいつもB2Fにいます。

正攻法で倒せました。

こいつよりお供の落とす錨ハンマーが大事。

また近くに悲哀の衣があるので回収しておきましょう。

極地の熊

小ボス。

この時点でもなんとか倒せますが、こいつの落とすものはまだ要らないのでスルーでOK。

収穫者

召喚してくる骸骨は前衛と中衛の打撃で一撃で処理していきましょう。

ガード不能の攻撃をしてくるので躱さないと死人が出ます。

寵臣の甲殻鎧の回避攻撃で避けるのを祈るしかありません。

それでも当たってしまったらやり直しの運ゲー

前衛

  • 錨ハンマー
  • 上質のカイトシールド
  • 寵臣の甲殻鎧

中衛

  • 強化クォータースタッフ
  • なし
  • 悲哀の衣

後衛

  • 狙撃手の長弓
  • なし
  • 勇壮の革鎧

炎のイフリート

B5Fで腕力の杖が手に入り、腕力の杖 + 杖使いのケープを装備したキャラに勇壮の革鎧が胆勇をかけると火力が跳ね上がります。

さっそく餌食になるのがこのイフリート。

前衛

  • 錨ハンマー
  • 上質のカイトシールド
  • キマイラの皮鎧

中衛

  • 腕力の杖
  • なし
  • 杖使いのケープ

後衛

  • 狙撃手の長弓
  • なし
  • 勇壮の革鎧

腕力の杖はこの後も大半の戦いにおいて主ダメージソースとなるので優先して強化します。

先触れ

最深層まで一度たどり着けると悲哀の衣を買うことができるので3人分揃えましょう。

生物にしか効かない攻撃をしてきたら無駄行動になり大幅にアドバンテージを取れます。

LVがある程度あればハームタッチも1回は耐えられるので楽です。

櫃の怪異

ドロップ率が上がるアイテムを落とすので早めに倒しておきたい敵。

こいつも生物にしか効かない攻撃をしてきます。

前衛

  • 錨ハンマー
  • 上質のカイトシールド
  • 悲哀の衣

中衛

  • 強化クォータースタッフ
  • なし
  • 悲哀の衣

後衛

  • 腕力の杖
  • なし
  • 杖使いのケープ

火力がほしいので1人は悲哀の衣は装備させずに火力要因にしました。狙われないように祈りましょう。

生い茂る放棄地の敵

ここに何度も通って装備を集めましょう。

優先度の高いのは霊峰の槌です。しかも2つ欲しい。献身的なアコライトを狩りまくりましょう。

2つ出るまでにはLVも上がって他の装備もだいたい1個ずつ集まるでしょう。

前衛

  • 山崩し -> 霊峰の槌
  • 防具は適宜数値の良いものが入ったら交換していく

中衛

  • 腕力の杖
  • なし
  • 杖使いのケープ

後衛

  • 大樹の弓
  • なし
  • 勇壮の革鎧

岩礁ハーピー x4

高い威力の弓なら一撃で1体倒せます(ただしLVと武器の強化が足りないと仕留めきれない)。

但し遠距離攻撃半減の技能を使われると落とせないので使わないときまで逃げてやり直す。

これで2ターンで終わります。

なお、こいつらの落とす円鱗の盾を2つ集めると火炎2発で1ターンで終わります。

かそけきウォルオウィスプ、大蜘蛛の幼体、ジャイアントキラー

こいつら全部、火炎で1ターンキルです。

厄除けのガーゴイル

石化がボーナス行動なので余裕でしょう。

適当に腕力の杖で殴り倒しましょう。

大樹の大盾は2つ集めましょう。

夜風のヒポグリフ

LV40ボスで一番弱いかもしれない。

火吐きを連発で余裕です。

ただし遠距離攻撃大幅カット技は困るので使われそうになったら霊峰の槌の氷結で妨害しましょう。

極地の熊

火吐きできるようになれば余裕です。

不凍マントを人数分作るまで通いましょう。

上級パイロマンサー x3、背徳インプ

側面からぶつかって先制攻撃しましょう。

  • 1ターン目に前衛が氷結、中衛が敵中衛に攻撃、後衛が胆勇
  • 2ターン目に中衛が敵前衛に攻撃

で2ターン目で敵は半壊です。

前衛

  • 霊峰の槌
  • 大樹の大盾
  • キマイラの皮鎧

中衛

  • 腕力の杖
  • なし
  • 杖使いのケープ

後衛

  • 霊峰の槌
  • 大樹の大盾
  • 勇壮の革鎧

美技のデーモン、まじないのデーモン

こいつらは2ターン氷結させればその間に腕力の杖で殴り倒せます。

血吸い曲刀

後衛は1ターン目に中衛に胆勇、2ターン目に敵前衛に氷結。

中衛は1ターン目2ターン目は狙われていればガード、そうでなければ攻撃。

敵が1体になって構え直しのターンで前衛が氷結、後衛が中衛に胆勇。

これでだいたい倒せます。中衛が狙われすぎるとたまに失敗します。

前衛

  • 霊峰の槌
  • 大樹の大盾
  • 奉献の板金鎧 -> 堅甲の板金鎧

中衛

  • 腕力の杖
  • なし
  • 杖使いのケープ

後衛

  • 霊峰の槌
  • 大樹の大盾
  • 勇壮の革鎧

岩石ゴーレム

四天王最弱。

命中は低いわ、硬そうに見えて打撃に弱いわ、HP自体も低い。

胆勇かけて3回殴れば終わり。凍結も絡めると2回で終わり。

前衛

  • 竜狩りの大剣
  • なし
  • 向こう見ずの服

中衛

  • 腕力の杖
  • なし
  • 杖使いのケープ

後衛

  • 霊峰の槌
  • 大樹の大盾
  • 勇壮の革鎧

鐘塔の巨大蜘蛛

お供を3体召喚しますが打撃武器ばかりのPTの敵ではありませんでした。

四天王弱い方から2番目。

樹氷ワイバーン

不凍マントさえ揃っていれば楽。

前衛、中衛

  • 適当な片手槍
  • 大樹の大盾
  • 不凍マント

後衛

  • 大樹の弓
  • なし
  • 不凍マント

黒衣の深淵

お供の庇うが厄介だが、氷結で凍らせれば次のターンは動けないのでそこを殴り倒す。

隔世のデーモン

HPが多く、氷結 + 胆勇殴りコンボで倒しきれない。

ということで大樹の大盾で回復しながら持久戦に持ち込みました。

後衛まであまり攻撃が飛んでこないことを良いことに、後衛は回復を捨てて弓で攻撃してます。

相手のHPが減ると攻撃が激化して隙がなかなかないですが、3巡くらいパターンを回ると精神力が切れて通常攻撃しかしなくなるので後はお好きに。

前衛

  • 守護者の剣
  • 大樹の大盾
  • 堅甲の板金鎧

中衛

  • ルーンの短槍
  • 大樹の大盾
  • 神秘の革鎧

後衛

  • 大樹の弓
  • なし
  • 獣性の鎧

ラスボス

隔世のデーモンと同じ対策で。

HPが1/4減るごとに攻撃パターンが変化しますが、最後の1/4まで減ったところで後衛がやられてしまいました。

しばらく耐えていたらまたも相手の精神力が切れてしまったので後は楽勝。

ワーウルフのチャンピオン

裏ボス? お供が3体いるのがつらいです。

行動がある程度ランダムなので無駄行動が出るまでやり直せばなんとか。

重装センチネルが1ターン目から庇うとつらく、そうでないときに献身的なアコライト、狼の森の狙撃手を速攻撃破できると勝機が。

前衛

  • 霊峰の槌
  • 大樹の大盾
  • 堅甲の板金鎧

中衛

  • 腕力の杖
  • なし
  • 杖使いのケープ

後衛

  • 大樹の弓
  • なし
  • 獣性の鎧

はてなブックマークの表示を変えたい(2)

前回の続き

ちょっとCSSいじりました。

はてなブックマークの表示を改変

  • カテゴリとドメイン名をタイトルの左に移動
  • 日時とタグ非表示
  • ガタガタしてたので幅調整 など。
#entrylist-ad-right-top {
    position: absolute;
    right: 0;
    z-index: 1;
    top: 32px;
}

.entrylist-wrapper {
    width: 100%;    
}

.entrylist-contents-title {
    min-height: 0px;
    width: 400px;
    order: 2;
    padding: 0;
    margin: 0;
}

.entrylist-header-main .entrylist-image-entry .entrylist-contents-title {
    padding-right: 0;    
}

.entrylist-contents-title a {
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    font-size: small;
}

.entrylist-item {
   width: 100%;    
}

.entrylist-header-main, .entrylist-item>li {
    flex-basis: auto;
    max-width: 100%;
    width: 100%;
}

.entrylist-contents-body {
    max-width: 60%;
}

.entrylist-item .entrylist-image-entry .entrylist-contents-description, .entrylist-contents-description {
    text-align: left;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    margin-bottom: 0;
}

.entrylist-contents-thumb{
    display:none;
}

.entrylist-contents-main {
    padding: 4px;
    flex-direction: row;   
}

.entrylist-contents-users {
    display: inline;
    text-transform: none;
    font-size: medium;
    right: auto;
}

.entrylist-contents-users a {
   display: inline;    
}

.entrylist-contents-users span {
    font-size: 14px;
}

.entrylist-contents-domain, .river-placement .entrylist-contents-domain {
    width: 130px;
    padding: 0.8rem 0 0 0.2rem;
    order: 1;
}

.entrylist-contents-meta {
    padding: 0;
    order: 0;
    width: 100px;
}

.entrylist-contents-meta li {
    margin-top: 20px;
}

.entrylist-contents-date {
    display: none;
}

.entrylist-contents-tags {
    display: none;
}

おまけ

特定のドメインの記事は見えなくしたい場合。

例として匿名ダイアリーを非表示にしたい場合。

li.js-keyboard-selectable-item:has(a[href="/site/anond.hatelabo.jp/"]) {
    display:none;
}

はてなブックマークの表示を変えたい(1)

はてなブックマークをPCのブラウザで見ると、1行に4つの記事が表示されていて、見るときに視線を左右に移動させないといけないのがちょっとつらい。

はてなブックマーク

1行1記事で基本上から下にだけ視線を移動させれば良いようにしたい。

ということでCSSを無理やり当てて表示を変更してみました。

改変はてなブックマークのSS
改変はてなブックマークのSS

ちょっとまだガタガタしている部分もありますが、気が向いたら直します。

やり方

StylusっていうChrome Extentionを使用しました。(Firefoxにもあります)

特定のサイトのCSSを上書きできるブラウザ拡張は他にもあるのでお好みのものをどうぞ。

CSS

.entrylist-wrapper {
    width: 100%;    
}

.entrylist-contents-title {
    min-height: 0px;
    width: 400px;
}

.entrylist-contents-title a {
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    font-size: small;
}

.entrylist-item {
   width: 100%;    
}

.entrylist-header-main, .entrylist-item>li {
    flex-basis: auto;
    max-width: 100%;
    width: 100%;
}

.entrylist-contents-body {
    width: 50%;    
}

.entrylist-item .entrylist-image-entry .entrylist-contents-description, .entrylist-contents-description {
    text-align: left;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    margin-bottom: 0;
}

.entrylist-contents-thumb{
    display:none;
}

.entrylist-contents-main {
    padding: 4px;
    flex-direction: row;   
}

.entrylist-contents-users {
    text-transform: none;
}

.entrylist-contents-users span {
    font-size: 10.5px;
}

.entrylist-contents-domain {
    padding: 0;   
}

.entrylist-contents-meta {
    padding: 0;
}

.entrylist-contents-tags {
    max-width: 200px;
    padding: 0;
}

余談

昔々は本家はてなブックマークも1行に1記事でした。

で。それが今の表示に変わってから元の行表示がほしいユーザーがいて、その人たちに嫁のはてぶっていうサイトが人気だったんですが、そこも閉鎖してしまってました。

PDFをプログラムで編集したい

既存のPDFにテキストを追加したい・・と思ったことありませんか?

今の時期なら国税庁が配布している確定申告書等のPDFに印字したい、とかでしょうか。

確定申告書等の様式・手引き等(令和5年分の所得税及び復興特別所得税の確定申告分)|国税庁

※なお、私はe-Taxで済ませたので実際のところは確定申告書を印刷したいわけではありません

画像として編集

PDFをjpgなりpngなりのラスター画像にして編集する方法。

画像にしてしまえばいくらでも文字を載せたりすることはできます。

が、欠点としては以下の点が挙げられます

  • 出力時の解像度が低いと印刷時に汚くなる
  • 出力時の解像度が高いとファイルサイズが大きくなる
  • テキストとしての情報が失われて画像になってしまうので再度の編集が難しくなる

ライブラリ

pdf.js

GitHub - mozilla/pdf.js: PDF Reader in JavaScript

pdf.jsはJavaScriptHTML5canvasにPDFを描画するためのライブラリ。

描画してからcanvasのtoDataURLを使うとPNGを出力できるが、当然テキストの情報は失われます。

無理やりpdf.jsが内部で持っているoperationのdataをいじれば内容は編集できるが、素のPDFの情報に近く、編集するのはかなり大変。

pdf-lib

https://github.com/Hopding/pdf-lib

jsのコードからテキストを追加できます。

ただしGUIはなく、位置を指定する必要がある(単位はポイント=1/72インチ?)。また文字ごとの間隔を調整したい場合は1文字ずつ印字、になりそう。

既存テキストの編集はできません(対応したいと言っているが3年位開発止まってる)。

HummusJS/MuhammaraJS

https://github.com/julianhille/MuhammaraJS

HummusJSが開発終了してMuhammaraJSに引き継がれた。

C++製ライブラリとそのjsラッパーなのでブラウザでは動作しない(だれかWebAssembly化して・・)

PDFBox

https://pdfbox.apache.org/

Java製ライブラリ。

テキストの追加は出来る。

まとめ

コードからPDFにテキスト追加できるライブラリはいくつかありましたが、既存テキストの編集は見つけられませんでした。

また、GUIからぽちぽちしてPDFを楽に編集できる方法はオープンソースのものでは見つけられませんでした。

GUIから操作したいときはAdobeAcrobatでも買いませう。

Chromeのページ内検索で正規表現を使いたい

タイトルの通り、Chromeのページ内検索で正規表現を使いたい、んですが、今までずっとむず痒さを覚えつつも放置してました。

使いたいケースは主にgithub上でコード読むとき。今まで正規表現で検索したいときはローカルにチェックアウトする、っていう無駄なことしてました。 (リポジトリからコードを探すときはgithubの機能で正規表現で検索できますが、今見てるファイル内を検索したいときに困っていました)

あと、Chromeの検索は大文字小文字区別しないので困ります。

そんなんextention作ってくれてる人いるだろう、と思ったら案の定ありました。ありがとうございます。

https://chromewebstore.google.com/detail/chrome-regex-search/bpelaihoicobbkgmhcbikncnpacdbknn

Firefoxは昔ブラウザ標準の機能で正規表現検索機能あったと思うんだけど少なくとも今はなさそう。大文字小文字の区別はできます。