前回、解いた
1時間以内に解けなければプログラマ失格となってしまう5つの問題が話題に
ですが、さすがにあんまりな内容だったので問題4と5の答えを改めてそれっぽい感じにつくってみました。
主に次のページを参考にしました。
http://qiita.com/tanakh/items/b4069a6d3485ef4278ce
http://techblog.mindpl.co.jp/2014/09/array_combination/
つまりカンニングしました。
問題4
正の整数のリストを与えられたとき、数を並び替えて可能な最大数を返す関数を記述せよ。例えば、[50, 2, 1, 9]が与えられた時、95021が答えとなる(解答例)。
<?php require_once 'util.php'; function p4(array $xs) { $xs = array_sort($xs, function($a, $b) { return "{$b}{$a}" < "{$a}{$b}"; }); return implode($xs); } echo p4([50, 2, 1, 9]). "\n";
$ php 4.php 95021
問題5
1,2,…,9の数をこの順序で、”+”、”-“、またはななにもせず結果が100となるあらゆる組合せを出力するプログラムを記述せよ。例えば、1 + 2 + 34 – 5 + 67 – 8 + 9 = 100となる(解答例)
<?php require_once 'util.php'; function calc($expr) { $f = function(array $acc, $term) { if ($term === '+') { $acc['x'] = $acc['f']($acc['x'], $acc['y']); list($acc['f'], $acc['y']) = ['add', 0]; } else if ($term === '-') { $acc['x'] = $acc['f']($acc['x'], $acc['y']); list($acc['f'], $acc['y']) = ['sub', 0]; } else if ($term === '=') { $acc['x'] = $acc['f']($acc['x'], $acc['y']); } else if ($term !== '') { $acc['y'] = $acc['y'] * 10 + $term; } return $acc; }; $expr[] = '='; $acc = array_reduce($expr, $f, ['x' => 0, 'f' => 'add', 'y' => 0]); return $acc['x']; } function is_n($n) { return function($expr) use($n) { return calc($expr) === $n; }; } function p5() { $nums = array_map('wrap_array', range(1, 9)); $opes = replicate(8, ['+', '-', '']); $exprs = array_filter(direct_product(alternate($nums, $opes)), is_n(100)); return array_map('implode', $exprs); } foreach (p5() as $expr) { echo $expr. "\n"; }
$ php 5.php 1+23-4+56+7+8+9 12+3-4+5+67+8+9 1+2+34-5+67-8+9 1+2+3-4+5+6+78+9 123-4-5-6-7+8-9 123+45-67+8-9 1+23-4+5+6+78-9 12-3-4+5-6+7+89 12+3+4+5-6-7+89 123-45-67+89 123+4-5+67-89
util.phpはこんな感じです。
<?php function array_sort(array $xs, $isAsc) { usort($xs, function($a, $b) use($isAsc) { return $isAsc($a, $b) ? -1 : 1; }); return $xs; } function alternate(array $xs, array $ys) { return $xs === [] ? $ys : array_merge([$xs[0]], alternate($ys, array_slice($xs, 1))); } function div_qr($n, $d) { return [intval($n / $d), $n % $d]; } function replicate($n, $x) { return array_map(function($n) use($x) { return $x; }, range(0, $n - 1)); } function add($x, $y) { return $x + $y; } function sub($x, $y) { return $x - $y; } function count_direct_product(array $xss) { $f = function(array $acc, array $xs) { $n = count($xs); $acc['direct_product'] *= $n; $acc['own']++; $acc['each'][] = $n; return $acc; }; return array_reduce($xss, $f, ['direct_product' => 1, 'own' => 0, 'each' => []]); } function direct_product(array $xss) { $count = count_direct_product($xss); $direct_product = []; for ($i = 0; $i < $count['direct_product']; $i++) { $combination = []; for ($q = $i, $j = 0; $j < $count['own']; $j++) { list($q, $r) = div_qr($q, $count['each'][$j]); $combination[] = $xss[$j][$r]; } $direct_product[] = $combination; } return $direct_product; } function wrap_array($n) { return [$n]; }
プログラマになりたいなぁ。