Perl(569文字)
use Math'BigInt;sub r{($u,$v)=@_;$v?r($v,$u%$v):$u}sub c{new Math'BigInt$_[0]}$a=@c=<>;for(@c){m!(-?\d+)/?(\d*). = (-?\d+)/?(\d*)!;$j{$_,$i}=$1**c$_,$k{$_,$i|=0}=($2||1)**c$_ for 0..$a;$j{$a,$i}=c$3;$k{$a,$i++}=c$4||1}for$p(0..$a-1){for$y(0..$p-1,$p+1..$a-1){$n=$j{$p,$y}*$k{$p,$p};$o=$k{$p,$y}*$j{$p,$p};$j{$_,$y}=$j{$_,$y}*$k{$_,$p}*$o-$k{$_,$y}*$j{$_,$p}*$n,$k{$_,$y}*=$k{$_,$p}*$o for 0..$a}}print"f(x)=";for(1..$a){$s=r$t=$j{$a,$p=$a-$_}*$k{$p,$p},$w=$k{$a,$p}*$j{$p,$p};$u=abs$t,print$t>0?"$z":'-',($z='+',$w/=$s)-1?"\\frac{$u}{$w}":$u,$p>1?"x^$p":x x$p if$t/=$s}
詳細な説明:
use Math'BigInt;
# Subroutine to calculate gcd of two numbers
sub r{($u,$v)=@_;$v?r($v,$u%$v):$u}
# Subroutine to create BigInts
sub c{new Math'BigInt$_[0]}
# Read input
# Throughout, $a is the number of equations.
$a=@c=<>;
# Initialises the $a+1 × $a matrix with all the values.
# $j{$x,$y} contains the numerator, $k{$x,$y} the denominator.
for(@c)
{
m!(-?\d+)/?(\d*). = (-?\d+)/?(\d*)!;
# Puzzle for the reader: why is $i|=0 in the second one,
# not the first one? Answer at the bottom!
$j{$_,$i}=$1**c$_,$k{$_,$i|=0}=($2||1)**c$_ for 0..$a;
$j{$a,$i}=c$3;
$k{$a,$i++}=c$4||1
}
# Generates the matrix echelon form.
# Basically, it works like this:
for$p(0..$a-1)
{
# For each element along the diagonal {$p,$p}, set all the values above and
# below it to 0 by adding a multiple of row $p to each of the other rows.
for$y(0..$p-1,$p+1..$a-1)
{
# So we need to multiply the row $p by the value of {$p,$y}/{$p,$p}
# (stored in $n/$o) and then subtract that from row $y.
$n=$j{$p,$y}*$k{$p,$p};
$o=$k{$p,$y}*$j{$p,$p};
$j{$_,$y}=$j{$_,$y}*$k{$_,$p}*$o-$k{$_,$y}*$j{$_,$p}*$n,
$k{$_,$y}*=$k{$_,$p}*$o
for 0..$a
}
}
# Outputs the result
print"f(x)=";
for(1..$a)
{
# Note this sets $p = $a-$_. $p is the power of x.
# We need to divide {$a,$p} by {$p,$p}. Store the result in $t/$w.
# We also need to put the fraction in lowest terms, so calculate the gcd.
$s=r$t=$j{$a,$p=$a-$_}*$k{$p,$p},$w=$k{$a,$p}*$j{$p,$p};
# Output this term only if the numerator ($t) is non-zero.
# Output a plus sign only if this isn’t the first term.
# Output a fraction only if the denomator ($w) isn’t 1.
$u=abs$t,print$t>0?"$z":'-',
($z='+',$w/=$s)-1?"\\frac{$u}{$w}":$u,$p>1?"x^$p":x x$p
if$t/=$s
}
# Answer to the puzzle buried in the code above:
# It’s because the second part is passed as a second argument to c,
# hence it is evaluated before the first part.
コメント
- 階層型の機能を提供するマトリックス操作用のモジュールがあると確信しています。私はそれを自分でやることがこのコンテストのポイントだと思うので、私は特にそれを使用しませんでした(検索することさえしませんでした)。その方がもっと面白いです。もちろん、BigIntについても同じことが言えますが、この挑戦を試みる人はいないと思います...
編集
(630→585) 2つのループではなく1つのループで階層型を実行できることに気付きました。説明をコードにコメントとして追加します。
(585→583)の'
代わりに使用できるパッケージ構文を発見しました::
。
(583→573)もう少しマイクロゴルフ
(573→569)入力を解析するための短い正規表現