diff --git a/problems/data/009-replace-all-delimiters.json b/problems/data/009-replace-all-delimiters.json new file mode 100644 index 0000000..8a2281e --- /dev/null +++ b/problems/data/009-replace-all-delimiters.json @@ -0,0 +1,53 @@ +{ + "id": "data-009", + "category": "data", + "difficulty": 2, + "start": [ + "1;alice;active", + "2;bob;active", + "3;carol;inactive" + ], + "goal": [ + "1,alice,active", + "2,bob,active", + "3,carol,inactive" + ], + "solutions": [ + { + "keys": ":%s/;/,/g", + "optimal": true + }, + { + "keys": ":1,3s/;/,/g" + } + ], + "tags": [ + ":s", + "substitute", + "csv" + ], + "i18n": { + "ja": { + "title": "区切り文字を一括で置換する", + "description": "すべてのセミコロンをカンマに置き換えてください", + "hints": [ + ":%s/old/new/g は全行のすべての一致を置換する" + ], + "notes": [ + ":%s/;/,/g の % は全行、末尾の g は行内のすべての一致を意味する", + ":1,3s/;/,/g のように範囲を数字で指定しても同じ結果になる" + ] + }, + "en": { + "title": "Replace every delimiter", + "description": "Replace every semicolon with a comma", + "hints": [ + ":%s/old/new/g substitutes every match on every line" + ], + "notes": [ + "In :%s/;/,/g the % means all lines and the trailing g means every match in each line", + "An explicit range like :1,3s/;/,/g does the same thing" + ] + } + } +} diff --git a/problems/data/010-strip-trailing-comma.json b/problems/data/010-strip-trailing-comma.json new file mode 100644 index 0000000..94891b7 --- /dev/null +++ b/problems/data/010-strip-trailing-comma.json @@ -0,0 +1,54 @@ +{ + "id": "data-010", + "category": "data", + "difficulty": 2, + "start": [ + "id,name,", + "1,alice,", + "2,bob," + ], + "goal": [ + "id,name", + "1,alice", + "2,bob" + ], + "solutions": [ + { + "keys": ":%s/,$//", + "optimal": true + }, + { + "keys": ":%normal $x" + } + ], + "tags": [ + ":s", + "substitute", + "regex", + "csv" + ], + "i18n": { + "ja": { + "title": "行末のカンマを消す", + "description": "各行の末尾のカンマを削除してください", + "hints": [ + "置換パターンの $ は行末にマッチする" + ], + "notes": [ + ":%s/,$// は全行の行末カンマだけを空文字に置換する", + ":%normal $x で全行に対して $x(行末へ移動して1文字削除)を実行しても同じ" + ] + }, + "en": { + "title": "Strip the trailing comma", + "description": "Delete the trailing comma on every line", + "hints": [ + "$ in a substitute pattern matches the end of the line" + ], + "notes": [ + ":%s/,$// replaces only the end-of-line comma with nothing on every line", + ":%normal $x runs $x (jump to end of line, delete one char) on every line for the same result" + ] + } + } +} diff --git a/problems/data/011-update-status-values.json b/problems/data/011-update-status-values.json new file mode 100644 index 0000000..73b5acc --- /dev/null +++ b/problems/data/011-update-status-values.json @@ -0,0 +1,52 @@ +{ + "id": "data-011", + "category": "data", + "difficulty": 2, + "start": [ + "1,alice,pending", + "2,bob,done", + "3,carol,pending" + ], + "goal": [ + "1,alice,done", + "2,bob,done", + "3,carol,done" + ], + "solutions": [ + { + "keys": ":%s/pending/done/", + "optimal": true + }, + { + "keys": ":%s/pending/done/g" + } + ], + "tags": [ + ":s", + "substitute" + ], + "i18n": { + "ja": { + "title": "ステータスをまとめて更新する", + "description": "すべての pending を done に置き換えてください", + "hints": [ + "1行に1回しか出てこない語なら g フラグは要らない" + ], + "notes": [ + ":%s/pending/done/ は各行の最初の一致だけを置換する。1行1回なのでこれで十分", + "g フラグを付けても結果は同じだが、この行では不要" + ] + }, + "en": { + "title": "Update the status values", + "description": "Replace every 'pending' with 'done'", + "hints": [ + "The g flag is unnecessary when the word appears once per line" + ], + "notes": [ + ":%s/pending/done/ substitutes the first match on each line, which is enough here", + "Adding the g flag gives the same result but is not needed on these lines" + ] + } + } +} diff --git a/problems/data/012-delete-blank-rows.json b/problems/data/012-delete-blank-rows.json new file mode 100644 index 0000000..7b5aca6 --- /dev/null +++ b/problems/data/012-delete-blank-rows.json @@ -0,0 +1,55 @@ +{ + "id": "data-012", + "category": "data", + "difficulty": 3, + "start": [ + "1,alice", + "", + "2,bob", + "", + "3,carol" + ], + "goal": [ + "1,alice", + "2,bob", + "3,carol" + ], + "solutions": [ + { + "keys": ":g/^$/d", + "optimal": true + }, + { + "keys": "jddjdd" + } + ], + "tags": [ + ":g", + "global", + "dd" + ], + "i18n": { + "ja": { + "title": "空行を取り除く", + "description": "データの間にある空行をすべて削除してください", + "hints": [ + ":g/pattern/d はパターンに一致する行をすべて削除する" + ], + "notes": [ + ":g/^$/d は空行(行頭がすぐ行末の行)だけを対象に d を実行する", + "空行が少なければ j で移動して dd を繰り返してもよい" + ] + }, + "en": { + "title": "Remove the blank rows", + "description": "Delete every blank line between the data rows", + "hints": [ + ":g/pattern/d deletes every line matching the pattern" + ], + "notes": [ + ":g/^$/d runs d on every empty line (start of line immediately followed by end of line)", + "With only a couple of blanks you can also just move with j and repeat dd" + ] + } + } +}