はじめに
最近弊社ゆめみでは, Twitter にて「ゆめみからの挑戦状」という企画を定期開催しています.
ゆめみの社員がプログラミングに関する問題を出して,皆さんに引用リツートで答えていただく,というものです.
歴代の出題者として Qiita でも有名な @Yametaro や @mpyw などがおりますが,今回は私が出題させていただきました!
本記事は,問題,想定解やその他皆さんからいただいたオモシロ回答などをご紹介します.
問題
<?php
$year = 2022;
$out = /* ここに回答を書いてください */;
var_dump($out);
/**
* $year を使って以下の配列を生成してください
* $out = [
* '202201',
* '202202',
* '202203',
* '202204',
* '202205',
* '202206',
* '202207',
* '202208',
* '202209',
* '202210',
* '202211',
* '202212',
* ];
*/
問題としては至ってシンプルで,「年」の情報から「年月」の配列を作るというものでした.
実際の業務でも,このような配列が必要になったことがある方もいらっしゃるのではないでしょうか?
回答の制約として,
- 処理はワンライナーで書かなければいけない(改行は可能)
- 「年」の情報は
int
で与えられるが,出力はstring[]
で出さないといけない
などがありますが,愚直な回答であればそんなに深く考えなくても解るくらいのレベル感だったと思います.
回答紹介
僕が思いつかなかった面白い回答も沢山ありました!
考えてくださった皆さん,ありがとうございました!
問題作成者推奨回答
ワイ「年の情報から年月の配列を出力すればええんやな!」
ワイ「って言っても,いまある情報は 2022 という整数一個だけやないか」
ワイ「整数からどうやって 12 個も要素を持つ配列を作ればええねん」
ワイ「もういっそ」
['1','2','3','4','5','6','7','8','9','10','11','12']
ワイ「っていう配列直接書いたろうかな...」
2歳息子くん「range()
使えばいいじゃん」
ワイ「ファ!?」
ワイ「息子くん!?」
ワイ「保育園行っとるんちゃうんけ」
息子「今日は有給とったよ」
ワイ「保育園で有給ってなんやねん」
ワイ「お金出しとるのはこっちやわ」
息子「そんなことより,連番の配列作るなら range()
が使えるよ」
息子「range($start, $end)
ってすれば」
息子「その範囲の整数を要素に持つ配列を作ってくれるんだよ」
ワイ「ほぇ〜,そんな関数があるんやね」
ワイ「じゃぁ,今回は 1 月から 12 月やから...」
$array = range(1, 12);
var_dump($array);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
ワイ「おぉ〜!」
ワイ「これ,もしかして ゆめみからの挑戦状 のために作られた機能なんちゃう?」
息子「そんなわけないでしょ」
息子「馬鹿なこと言ってないで続き解いたら?」
ワイ「せ,せやな...」
ワイ「要素数 12 の配列ができたら,これをループで回せば良さそうやな」
ワイ「今回の問題はワンライナーでかかんといかんから」
ワイ「array_map()
とかどうやろ?」
息子「うん,よさそう」
ワイ「よし,じゃぁ array_map()
を使って書いてみるで」
$out = array_map(function(int $month) use ($year) {
// ここに処理を書く
}, range(1, 12));
ワイ「とりあえず array_map()
だけ書いてみたけど...」
ワイ「この第一引数に渡すクロージャには」
ワイ「2022 という年の情報と 1 とか 2 という月の情報をくっつけて文字列として返す って処理をかけばええんやな」
ワイ「色々方法がありそうやな」
ワイ「例えば...」
$year = 2022;
$month = 1; // 1月
$yearMonth = sprintf('%d%02d', $year, $month);
ワイ「こんなかんじで splintf
を使って文字列に埋め込むとかどうやろ」
ワイ「ちゃんと 0 埋めもできていい感じや!」
ワイ「息子くんはどうや?」
息子「パパのやついいね!」
息子「The 模範解答 って感じがする」
息子「僕はね...」
$year = 2022;
$month = 1; // 1月
$yearMonth = (string)$year * 100 + $month;
息子「せっかく year も month も int
として渡ってくるから」
息子「year を 100 倍して month を足すと」
息子「明示的に 0 埋めしなくてもいい感じになるし」
息子「それを文字列にキャストしてあげれば期待通りになるよ!」
ワイ「ほんまや...!」
ワイ「天才やな!」
ワイ「じゃぁ,ワイと息子くんの回答をそれぞれちゃんとまとめると」
// ワイ
$out = array_map(function(int $month) use ($year) {
return sprintf('%d%02d', $year, $month);
}, range(1, 12));
// 息子くん
$out = array_map(function(int $month) use ($year) {
return (string)$year * 100 + $month;
}, range(1, 12));
ワイ「こんな感じやな!」
息子「クロージャの中でやる処理が 1 行に収まるなら」
息子「アロー関数を使って...」
// ワイ
$out = array_map(fn (int $month) => sprintf('%d%02d', $year, $month), range(1, 12));
// 息子くん
$out = array_map(fn (int $month) => (string)$year * 100 + $month, range(1, 12));
息子「こう書いてしまえば use
を使わなくて済むしスッキリするよ」
ワイ「おぉ〜,ほんまや!」
ワイ「ちょっとコードゴルフ感も出てきたな!」
皆さんの回答
模範解答的なもの,コードゴルフ的なもの,面白いものなど様々なパターンがありました!
一般部門
僕の回答に近いですが, $year
を直接埋め込んだタイプですね!
range()
に year まで含んで, strval()
で整数から文字列に変換するタイプです.これもアリ!
PHP の array_merge()
の第一引数に渡すのは,関数名(文字列)でもいけちゃうんです...!
今回の問題は年月を扱う日付操作と捉えて, Datetime を使って回答してくださいました!
DatePeriod クラスというものを知らなかったんですが,こんなのがあったんですね!
大喜利部門
必ず一人はいる,コメントから無理やり取ってくるタイプですw
とりあえず作れるだけ作って,あとから必要な分だけピックアップするタイプですw
うーん,お金に余裕がありそうな回答だ!
ちゃんと ”1 行” に収めてくださいました...!w
なにが起こってるんですか...?
yyyymmyyyymmyyyymm... となるような割り算を逆算してくれたんですかね...?w
この発想はなかった...
シェル芸パターンですね!
3V4L では実行できませんが...
この他にも,沢山素敵な回答をいただき,ありがとうございました!
終わりに
まずはご参加いただきありがとうございました!
知らない PHP の機能を使っているものもあり,僕自身も勉強になりました!
今後も面白い問題がどんどん出題される予定なので,よろしくおねがいします!