[過去ログ] プログラミングのお題スレ Part21 (1002レス)
上下前次1-新
抽出解除 レス栞
このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
638(32): 638 [sage] 2023/05/05(金) 15:50:16.77 ID:ZEoAaBzl(1/2) AAS
>>631 Perl5
$len = length ($s = 'mississippi');
for $a (0..$len-2) {
for $l (1..$len-$a) {
$t = substr($s, $a, $l);
$b = index($s, $t, $a+1);
$h{length $t} = $t if 0 <= $b
}
}
print $h{(sort keys %h)[-1]}, "\n";
注: インデントは全角スペースに置換してあります
実行結果
~ $ perl 21_631_mississippi.pl
issi
641: デフォルトの名無しさん [sage] 2023/05/05(金) 23:20:24.37 ID:ZEoAaBzl(2/2) AAS
>>638
重複を検出した文字の長さが二けた以上になる場合にも対応させるには
print $h{(sort keys %h)[-1]}, "\n";
↓
print $h{(sort{$a <=> $b} keys %h)[-1]}, "\n";
だな。
643: 638 [sage] 2023/05/06(土) 00:28:50.96 ID:vZgCL7uL(1) AAS
>>642642(4): 634 [] 2023/05/05(金) 23:33:20.01 ID:i3ZizMLE(1) AAS
>>640
そんなに簡単に解かれるとは思ってなかった
王国の話に引っ張られて解けない人いるかもと思ってた
3分割に限定したのが良くなかったかも
お題
文字列の分割パターンを全部列挙してください
入力: いろはにほ
出力:
い・ろ・は・に・ほ
い・ろ・は・にほ
い・ろ・はに・ほ
い・ろ・はにほ
い・ろは・に・ほ
い・ろは・にほ
い・ろはに・ほ
い・ろはにほ
いろ・は・に・ほ
いろ・は・にほ
いろ・はに・ほ
いろ・はにほ
いろは・に・ほ
いろは・にほ
いろはに・ほ
いろはにほ
Perl5
use utf8;
binmode STDOUT => "utf8";
use feature qw{:5.16 signatures say};
say for sub($a, @b) {
if (@b) {
my @s = __SUB__->(@b);
(map{"$a・$_"} @s), (map{"$a$_"} @s);
} else { $a }
}->(split'', 'いろはにほ');
※インデントは全角スペースに置換してあります。
perl5の__SUB__は、5.16以降で使用可能な「現在の関数(この場合無名関数)のリファレンス」
実行結果
~ $ perl 21_642_いろはにほ.pl
い・ろ・は・に・ほ
い・ろ・は・にほ
い・ろ・はに・ほ
い・ろ・はにほ
い・ろは・に・ほ
い・ろは・にほ
い・ろはに・ほ
い・ろはにほ
いろ・は・に・ほ
いろ・は・にほ
いろ・はに・ほ
いろ・はにほ
いろは・に・ほ
いろは・にほ
いろはに・ほ
いろはにほ
719: 638 [sage] 2023/06/04(日) 19:16:56.02 ID:pcjKLYRK(1/3) AAS
>>714714(3): デフォルトの名無しさん [] 2023/06/01(木) 22:06:54.62 ID:+6RwHPfX(2/2) AAS
お題:矩形に整形された全角文字のテキストが与えられる。左上から時計回りに
渦巻き状に読んだ文字列を、元の矩形と同文字数で桁数がより多く最も近い矩形に
左上から時計回りに渦巻き状に並べて出力せよ。
[例]
プログラ → プログラミン
題スレミ レス題おのグ
おのグン
[問題]
メロスは激怒した。必ず、かの邪智暴虐の王を除かなけ
ては、人一倍に敏感であった。きょう未明メロスは村れ
し、内気な妹と二人暮しだ。この妹は、村の或る律をば
対の嫁の衣裳やら祝宴の御馳走やらを買いに、は気出な
に六花ロスには竹馬の友があった。セリヌンテるな発ら
悪十、メてみるつもりなのだ。久しく逢わなィば一しぬ
邪。え。ねスは、まちの様子を怪しく思っかウる牧、と
もいゆた訪ロのは当りまえだが、けれどたっス市人野決
ど無れいらメい全体が、やけに寂しいも。たでにをを意
れもそ歩かに暗市不安になって来た。、ひのあや、越し
け房、られちの、ん衆をつかまえ。のなっだるっ近えた
。女はぶこうちくだい若たっ逢で路んんそか。て々山。
た。スら、るま無んだ、もスロメなきだりら今来、越メ
来いロぶをい、はでりかばいせの夜、かし、はた花えロ
て無メを友ててち落も日に既うも。るいて訪此の婿、ス
しも。路のい歩。るあでみし楽がのく行てねのだと十に
暮母る大そ。るいてしを工石、で市のスクラシ。し里は
で、あの都らかれそ、め集い買を々品のそ、ず先ては政
んもでのなか近間も式婚結。たいてっなに事るえ迎な治
遊父はにスロメ。た来てっやに市のスクラシの此たれが
と羊、き吹を笛。るあで人牧の村、はスロメ。ぬらかわ
Perl5
外部リンク:www.ideone.com
720(1): 638 [sage] 2023/06/04(日) 20:52:10.72 ID:pcjKLYRK(2/3) AAS
>>712712(5): デフォルトの名無しさん [] 2023/06/01(木) 09:25:39.43 ID:dfYyQvOG(1) AAS
お題
アルファベットが入力されます
> [A, A, B, B, B, C, C, D, D, D, E]
出力上限が入力されます
> 7
出力上限以内のアルファベットを出力してください
> [A, A, B, B, B, C, C]
ただし、出力上限で切った場合に同じアルファベットが分割される場合は出力上限を超えて
同じアルファベットが続く限り出力してください
アルファベット: [A, A, B, B, B]
出力上限: 3
出力: [A, A, B, B, B]
Perl5
use feature qw{signatures say};
sub f($n, $c, @s) {
if (1 < $n) {
$c, f($n - 1, @s);
} elsif (1 == $n) {
$c, f(0, $c, @s);
} else {
$c, f(0, $c, splice @s, 1) if $c eq $s[0];
}
}
say f 7, qw[A A B B B C C D D D E];
say f 3, qw[A A B B B];
※見易くするためインデントは全角スペースに置換してあります。
実行結果
$ perl 21_712.pl
AABBBCC
AABBB
721: 638 [sage] 2023/06/04(日) 23:24:30.12 ID:pcjKLYRK(3/3) AAS
>>712 Perl5、もっと簡潔なやり方あるんだった…orz
use feature qw{signatures say};
sub f($n, $s) {
my $r = '^.{' . ($n - 1) . '}(.)\1*';
$s =~ /$r/;
$&;
}
say f 7, 'AABBBCCDDDE';
say f 3, 'AABBB';
実行結果
$ perl 21_712_rex.pl
AABBBCC
AABBB
724: 638 [sage] 2023/06/05(月) 20:41:22.90 ID:4V5NjjYa(1/3) AAS
>>720 もっとすんなり書けるんだった… orz
$c, f(0, $c, splice @s, 1) if $c eq $s[0];
↓
$c, f(0, @s) if $c eq $s[0];
関数全体のコードとしてはこうなる:
sub f($n, $c, @s) {
if (1 < $n) {
$c, f($n - 1, @s);
} elsif (1 == $n) {
$c, f(0, $c, @s);
} else {
$c, f(0, @s) if $c eq $s[0];
}
}
すっきりした形になりました
725: 638 [sage] 2023/06/05(月) 21:31:53.30 ID:4V5NjjYa(2/3) AAS
>>722722(7): デフォルトの名無しさん [sage] 2023/06/05(月) 17:20:26.45 ID:41NWmDDP(1) AAS
お題 逆順に
文字列が与えられます
使われている文字のリストを作って並べその“反対の”文字を対応させます
例えば登場文字列が
HELLO WORLD
なら出てくる文字をコード順に並べると
" DEHLORW"
であるので
E → O, L →H, ' '→W
となります(空白、句読点等一切区別せず一文字と考えます)
この対応で入力された文字列を変換してください
例
HELLO WORLD →
LOHHEW EDHR
⑨⑫⑦②⑤⑭⑰⑳㉔①⑩⑬㉒⑲④⑮⑪⑧㉓⑥③⑯㉑⑱ →
⑯⑬⑱㉓⑳⑪⑧⑤①㉔⑮⑫③⑥㉑⑩⑭⑰②⑲㉒⑨④⑦
Perl5
use feature qw{signatures say};
use utf8; binmode STDOUT => 'utf8';
use Encode 'encode';
sub f($s) {
@s = split '', $s;
%h = map{unpack('H*', encode('utf-8', $_)) => $_} @s;
@i = reverse @c = sort keys %h;
%o = map{$h{$c[$_]} => $h{$i[$_]}} 0..$#c;
say map{$o{$_}} @s;
}
f 'HELLO WORLD';
f '⑨⑫⑦②⑤⑭⑰⑳?①⑩⑬?⑲④⑮⑪⑧?⑥③⑯?⑱';
※見易くするためインデントは全角スペースに置換してあります。
実行結果:
$ perl 21_722.pl
LOHHEW EDHR
⑯⑬⑱?⑳⑪⑧⑤①?⑮⑫③⑥?⑩⑭⑰②⑲?⑨④⑦
726(2): 638 [sage] 2023/06/05(月) 21:35:18.29 ID:4V5NjjYa(3/3) AAS
>>722 Perl5 スマソ、ビューワーから書き込んだら丸数字の一部が文字化けしたのでブラウザから再書き込み
use feature qw{signatures say};
use utf8; binmode STDOUT => 'utf8';
use Encode 'encode';
sub f($s) {
@s = split '', $s;
%h = map{unpack('H*', encode('utf-8', $_)) => $_} @s;
@i = reverse @c = sort keys %h;
%o = map{$h{$c[$_]} => $h{$i[$_]}} 0..$#c;
say map{$o{$_}} @s;
}
f 'HELLO WORLD';
f '????????㉔???㉒?????㉓???㉑?';
実行結果
$ perl 21_722.pl
LOHHEW EDHR
???㉓?????㉔????㉑?????㉒???
728: 638 [sage] 2023/06/06(火) 01:24:29.34 ID:gRU+jG8g(1/2) AAS
>>726 しくった
utf-8文字を可変長16進数にunpackして辞書的順番でsortするので、例題では意図した通りの結果を得られたが、
半角と全角などutf-8でバイト数の異なる文字が混在する文字列の場合には、順番が違ってくるだろうな…
729: 638 [sage] 2023/06/06(火) 02:40:16.03 ID:gRU+jG8g(2/2) AAS
>>726 Perlで文字の数値コードを返すord()関数は半角文字の場合にASCIIコードを返すが、
全角Unicode文字ではコードポイントを返す、ということなので、素直にそれを使い、
文字列としてっではなく数値としてsortし
%h = map{unpack('H*', encode('utf-8', $_)) => $_} @s;
@i = reverse @c = sort keys %h;
↓を
%h = map{ord($_) => $_} @s;
@i = reverse @c = sort{$a <=> $b} keys %h;
と修正するのがよさげ。連投スマソ
734: 638 [sage] 2023/06/08(木) 01:33:27.84 ID:GaLhBmy3(1) AAS
>>733733(3): デフォルトの名無しさん [] 2023/06/07(水) 23:16:05.89 ID:ijTNramp(1) AAS
お題
A,B,Cがランダムにいくつか入力されます
隣り合う文字が異なるときそれらは同じグループです
A,B → [A,B]
隣り合う文字が同じ時それらは異なるグループです
A,A → [A],[A]
A,B,A,A,A,B → [A,B,A],[A],[A,B]
もっとも長いグループを出力してください
入力
B,A,B,C,B,B,B,A,C,C,A,B,A,A,C,A,B,C,C,C,B,C,A,B,C,A,A,A,C,B
出力
[C,B,C,A,B,C,A]
Perl5
use feature qw{:5.16 signatures say};
@a = ([]);
sub ($c, @s) {
push @{$a[-1]}, $c;
push @a, [] if $c eq $s[0];
__SUB__->(@s) if @s;
}->(qw{B A B C B B B A C C A B A A C A B C C C B C A B C A A A C B});
$c = (sort{@$a <=> @$b} @a)[-1];
$" = ','; say "[@$c]";
※見易くするためインデントを全角スペースに置換してあります。
実行結果
$ perl 21_733.pl
[C,B,C,A,B,C,A]
761(6): 638 [sage] 2023/06/11(日) 02:58:42.46 ID:aJTqIDxz(1/2) AAS
力ずく問題は苦手なインタプリタ―だが、速度に配慮した書き方をすればこの規模だと数分程度で解ける…
use feature qw{:5.16 signatures say};
$m = 1234567;
%h = map{$_ => ++$k} 2..$m;
for $i (2..int(sqrt $m)) {
if (exists $h{$i}) {
for ($i..(int($m / $i)+1)) { delete $h{$i * $_} }
}
}
@p = sort{$a <=> $b} keys %h;
%o = map{$p[$_] => $_} 0..$#p;
for $i (0..$#p-2) {
$p1 = $p[$i];
last if $m <= 3 * $p1;
for $j ($i+1..$#p-1) {
$p2 = $p[$j]; $s = $p1 + $p2;
$r = $m - $s; last if $r <= $p2;
$n++ if exists $o{$r};
}
}
print "n = $n\n";
実行結果 (CPUは Core-i7 8995u、Mem: 32GB)
$ time perl 21_738_prime+1234567.pl
n = 151055501
real 5m48.035s
user 5m44.468s
sys 0m3.250s
出題者の解と合わん…><
762: 638 [sage] 2023/06/11(日) 03:01:19.54 ID:aJTqIDxz(2/2) AAS
>>761 アンカーしくった><
>>738738(13): デフォルトの名無しさん [] 2023/06/08(木) 22:14:54.10 ID:B/+C/EDE(2/2) AAS
お題:1234567以下の素数 a, b, c で a + b + c = 1234567 かつ a ≤ b ≤ c を満たす組み合わせは何通りあるか計算せよ。
Perl5
764: 638 [sage] 2023/06/11(日) 22:49:44.46 ID:7781B+HK(1) AAS
>>763763(2): デフォルトの名無しさん [] 2023/06/11(日) 20:59:06.26 ID:MUXJWS2B(2/2) AAS
>>761
インタプリタでもRだともっと速い。以下のプログラムを https: //tio.run で実行すると
9.96秒で完了し、解は>>746の151060650通りと合う。>>761は制限時間 (1分) 以内に
完了しない。Rは自前のループをなるべく書かずにベクトル演算にすれば割と速い。
n <- 1234567L
isprime <- c(FALSE, rep(TRUE, n - 1))
for (i in 2:sqrt(n)) if (isprime[i]) isprime[seq(i + i, n, i)] <- FALSE
p <- which(isprime)
q <- cumsum(isprime)
k <- 0L
for (i in p[1:q[n %/% 3L]]) {
m <- n - i
k <- k + sum(isprime[m - p[q[i]:q[m %/% 2L]]])
}
cat(k, "通り\n", sep = "")
Perlの(多分Pythoも,Rubyはシラネ)配列はリストなのでインデックスで回すとリンク辿りをloopで繰り返し
こういったコードでは遅さに拍車をかけていると思う。あとhashを多用するのもペナルティーがあると思う。
配列の代わりにBit Vectorが使える場面ではそれにより改善できる可能性がある
たとえば序盤のエラトステネスの篩で素数求めるloopについては>>761のコードだと5.2秒くらいなんだけれど
長い文字列をVectorとし、個々の文字をflag要素とみなし、
use feature qw{say};
$m = 1234567;
$o = '1' x $m;
for $i (2..int(sqrt $m)) {
if (substr $o, $i, 1) {
for ($i..(int($m / $i)+1)) {
$j = $i * $_; last if $m <= $j; substr $o, $j, 1, '0';
}
}
}
for (2.. $m) {
$n++ if substr($o, $_, 1);
}
print "$n\n";
と書くと0.3秒くらいに短縮される。ただし5分のうち5秒なので焼け石に…
しかしこの方法は151060650通りを求める後半のループにはうまく効かない。
つかそれ以前に解が合ってない。多分俺が勘違いしてバグ仕込んだと思う。
しかしRのコード短いな…も一回勉強してみようかな
769: 638 [sage] 2023/06/12(月) 23:47:34.40 ID:zjICvCkc(1) AAS
>>766766(2): デフォルトの名無しさん [] 2023/06/12(月) 23:18:04.33 ID:Qrbs+YQO(1/2) AAS
>>763のプログラムの8〜11行目は以下のように書いた方がすっきりして良い。
for (i in 1:q[n %/% 3L]) {
m <- n - p[i]
k <- k + sum(isprime[m - p[i:q[m %/% 2L]]])
}
>>761のプログラムはa ≤ b ≤ cではなくa < b < cの場合の組み合わせ数を計算している。
14行目の$i+1を$iに、13行目と16行目の<=を<に変更すれば正解が得られる。
おお、指摘ありがとう。
俺てっきりa < b < cを検索する問題だと思い込んでた。何故合わないか頭ひねっていた。
思い込みにより作りこんだバグというものはなかなか自力で問題だと気づけないんだよな…。
>>767767(1): デフォルトの名無しさん [] 2023/06/12(月) 23:18:28.27 ID:Qrbs+YQO(2/2) AAS
PowerShell 7は前のバージョンよりは速くなっていて、以下のプログラムは>>761の
3分の1ほどの時間で実行できた。
$n = 1234567
$isprime = @($false) * 2 + @($true) * ($n - 1)
foreach ($i in 2..[Math]::sqrt($n)) {
if ($isprime[$i]) {for ($j = $i + $i; $j -le $n; $j += $i) {$isprime[$j] = $false}}
}
$j = 0
$p = $q = @(0) * ($n + 1)
foreach ($i in 2..$n) {
if ($isprime[$i]) {$p[$j++] = $i}
$q[$i] = $j - 1
}
$k = 0
foreach ($i in 0..$q[$n / 3]) {
$m = $n - $p[$i]
foreach ($j in $i..$q[$m / 2]) {
if ($isprime[$m - $p[$j]]) {$k++}
}
}
"${k}通り"
俺も時間あったら高速化してみるよ。そのうち…、時間があったら…
第二loopの高速化は他にも試作したけどちょっとムズカしい
770: 638 [sage] 2023/06/13(火) 00:40:44.65 ID:XM8TxFLS(1) AAS
>>738 Perl5 高速化版、>>766のおかげで不具合解決したし、>>761 の1/3に時間短縮できたので俺としてはこのお題これで一区切りつけたい。
$m = 1234567;
$o = '1' x $m; #substr $o, 0, 2, '00';
for $i (2..int(sqrt $m)) {
if (substr $o, $i, 1) {
for ($i..(int($m / $i)+1)) {
$j = $i * $_; last if $m <= $j; substr $o, $j, 1, '0';
}
}
}
for (2.. $m) { push @p, $_ if substr($o, $_, 1) }
for $i (0..$#p) {
$p1 = $p[0];
last if $m < 3 * $p1;
for $p2 (@p) {
$s = $p1 + $p2;
$r = $m - $s;
last if $r < $p2;
$n++ if substr $o, $r, 1;
}
shift @p;
}
print "n = $n\n";
実行結果:(CPU Core-i7 8995u)
$ time perl 21_738_prime+1234567_charVec.pl
n = 151060650
real 1m57.390s
user 1m56.375s
sys 0m0.093s
782: 638 [sage] 2023/06/15(木) 01:38:57.15 ID:znvLwevo(1) AAS
へー、そりゃ面白い
817: 638 [sage] 2023/06/21(水) 07:20:53.86 ID:oE07EYTe(1) AAS
>>805805(1): デフォルトの名無しさん [sage] 2023/06/16(金) 23:47:11.07 ID:xSzkTILM(1) AAS
>>795
とりあえずHaskell
10000項くらいまではちゃんと動くよう
Haskellの整数型は一応規格上の制限はないみたいだけど多分GHCには流石に制限あるだらうから何項まで動くか不明
Haskellのオジチャンは 一体どこに回答を書いたんだろう…
829: 638 [sage] 2023/06/23(金) 00:36:01.83 ID:+Wf7JNOC(1) AAS
>>811-812 Perl5、若いころ物理数学で勉強した記憶を呼び戻しながら、LibraryやComplex型を使用せず、また複素数をタプルで表して愚直に実装してみた。
長さが2のべき乗とのことだがバタフライ演算による計算量の低減は実装していない。なお10^-15乗などの微小な数値の仮数部がお手本解と異なるところがあるが計算誤差によるもので実質0だと思う。
(やっぱ記号を使った数式よりも物理的な意味やイメージと対応付けて捉える方が俺にとってはしっくりくるわ)
use utf8;
use constant PI => 3.141592653589793;
use feature qw{signatures say};
sub 基底($波数, $N) { [map{[cos(2*PI*$波数*$_/$N), sin((2*PI*$波数*$_/$N))]} 0..$N-1] }
sub 複素数の積($a, $b) { [$$a[0]*$$b[0] - $$a[1]*$$b[1], $$a[0]*$$b[1] + $$a[1]*$$b[0]] }
use List::Util 'reduce';
sub 積和相関($x, $e) { reduce{[$$a[0]+$$b[0], $$a[1]+$$b[1]]} map{複素数の積 $$x[$_], $$e[$_]} 0..$#$e }
sub FT(@s) { map{ 積和相関(\@s, 基底($_, scalar @s)) } 0..$#s }
sub iFT(@s) { my $n = @s; map{[$$_[0]/$n, $$_[1]/$n]} map{ 積和相関(\@s, 基底(-$_, $n)) } 0..$n-1 }
sub CV($a, $b) { my @c = FT(@$a); my @d = FT(@$b); iFT( map{複素数の積 $c[$_], $d[$_]} 0..$#c ) }
sub prti { join(', ', map{"$$_[0]". (0 <= $$_[1] and '+') ."$$_[1]i"} @_) }
my @a = ([1, 0], [2, 0], [3, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]);
my @b = ([4, 0], [5, 0], [6, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]);
say 'FT: ', prti FT(@a);
say 'CV: ', prti CV(\@a, \@b);
実行結果
$ perl 21_811_FT_CV.pl
FT: 6+0i, 2.41421356237309+4.41421356237309i, -2+2i, -0.414213562373095-1.5857864376269i, 2-4.89858719658941e-16i, -0.414213562373094+1.58578643762691i, -2-2i, 2.41421356237309-4.4142135623731i
CV: 4+2.66453525910038e-15i, 13+1.77635683940025e-15i, 28+8.88178419700125e-16i, 27-5.77315972805081e-15i, 18-1.77635683940025e-15i, -6.21724893790088e-15-7.99360577730113e-15i, 8.88178419700125e-15+7.105427357601e-15i, 1.24344978758018e-14-2.8421709430404e-14i
842: 638 [sage] 2023/06/24(土) 00:18:48.24 ID:2bg5q6qP(1) AAS
>>830830(6): デフォルトの名無しさん [sage] 2023/06/23(金) 12:40:23.36 ID:13UCTwmm(1) AAS
お題(難易度★★)
0, 1, 2, 3, 6, 11, 20, 37 ...
上記の数列の法則を元に、n番目の整数aを求めるプログラムを作成せよ
【条件】
3 <= n <= 1000
【例】
n=6なら、a=11となる
n=9なら、a=68となる
Perl5
use feature qw{signatures say}; no warnings 'experimental';
use bigint;
sub g($n, @a) {
push(@a, $a[-3]+$a[-2]+$a[-1]) while @a < $n;
$a[-1];
}
say g($_, (0, 1, 2)) for 6, 9, 1000;
#見易くするためインデントは全角スペースに置換してあります。
実行結果(CPU: Core-i7 8559u)
$ time perl 21_830.pl
11
68
1258890285439289522674621215321790399357402658069918084564035590888323288383996894058630489346490443306057821146808944309219589954636534445475146599057985479816395429617207869586544429749851128733512216004490332659216184693670760709292866744282443549293609850952277
real 0m0.143s
user 0m0.061s
sys 0m0.062s
878: 638 [sage] 2023/07/03(月) 00:25:45.25 ID:HgLiPfoF(1) AAS
>>875875(4): デフォルトの名無しさん [sage] 2023/07/02(日) 17:45:16.73 ID:bkSdQ5Ko(1) AAS
お題:半角スペースで区切られた単語が並ぶ文字列がある
この文字列を単語に分割してソートして配列にして返す関数を実装せよ
Perl5、出現した単語の重複を許容するか、あるいはuniqにするか明確でないけど、下記は許容する方法
sub f { sort shift =~ /(\w+)/g }
実行結果
外部リンク:ideone.com
890(1): 638 [sage] 2023/07/05(水) 23:15:53.66 ID:RHYedEAt(1) AAS
Parser generator使って自前で構文解析&計算させようとして苦戦していた俺涙目
898(2): 638 [sage] 2023/07/08(土) 18:46:12.49 ID:fDz284w7(1/4) AAS
>>884884(6): デフォルトの名無しさん [] 2023/07/04(火) 22:31:52.02 ID:0YaO2gnD(2/2) AAS
お題:62進数の計算
62進数の整数の加・減・乗算から成る式の文字列が入力される。計算結果を62進数の文字列で出力せよ。
ただし、10進数の0〜9, 10〜35, 36〜61に相当する数字にはそれぞれ0〜9, A〜Z, a〜zを用い、
計算の途中経過と最終結果は64ビット符号付き整数の範囲内に収まると想定して良い。
[例]
入力: 123 + ABC
出力: 123 + ABC = BDF
[問題]
2023-7-4
printf - (Hello + world)
Windows * 11
The - quick - brown * fox + jumped - over + the - lazy * dog
ABCDEFG + HIJKLMNOP + QRSTUV + WXYZ
Perl5、見易くするためインデントは全角スペースに置換してあります。
use feature qw{signatures}; no warnings 'experimental';
use Parse::RecDescent;
sub ope($valp, @args) { my $val = $valp->();
while (@args) { my ($op, $parm) = splice @args, 0, 2; $op->($val, $parm->()); } $val }
%d = map{$_ => $i++} 0..9,'A'..'Z','a'..'z';
%e = map{$d{$_} => $_} keys %d;
use List::Util 'reduce';
sub dec($d62) { reduce {$a*62 + $b} map{$d{$_}} split '', $d62 }
my $parse = new Parse::RecDescent <<'End';
expr: <leftop:term addsub term> {sub { ::ope @{$item[1]} }}
addsub: '+' {sub { $_[0] += $_[1] }} | '-' {sub { $_[0] -= $_[1] }}
term: <leftop:factor muldiv factor> { sub {::ope @{$item[1]} }}
muldiv: '*' {sub { $_[0] *= $_[1] }} | '/' {sub { $_[0] /= $_[1] }}
factor: dig62 | '(' expr ')' { $item[2] }
dig62: /[0-9A-Za-z]+/ {sub { ::dec $item[1] }}
End
sub enc($d) { my $r = $d % 62; $d = int(($d - $r) / 62); $d ? (enc($d) . $e{$r}) : $e{$r}; }
for (<DATA>) {
$n = $parse->expr($_)->();
$n = $n < 0 ? '-' . enc(-$n) : enc($n);
print "$_ = $n\n";
}
__DATA__
123 + ABC
4 - K
2023-7-4
printf - (Hello + world)
Windows * 11
The - quick - brown * fox + jumped - over + the - lazy * dog
ABCDEFG + HIJKLMNOP + QRSTUV + WXYZ
899: 638 [sage] 2023/07/08(土) 18:47:35.93 ID:fDz284w7(2/4) AAS
>>898 の実行結果:
$ perl 21_884_calc_dig26.pl
123 + ABC
= BDF
4 - K
= -G
2023-7-4
= 201s
printf - (Hello + world)
= odFAME
Windows * 11
= XFWRSlos
The - quick - brown * fox + jumped - over + the - lazy * dog
= -Q1YGAW2x
ABCDEFG + HIJKLMNOP + QRSTUV + WXYZ
= HITvzYcgj
※ Parse::RecDescentという再帰降下型Parser generatorのperl moduleを使用したので、
動作させるにはそのインストールされている必要がありますが、ideonなどのオンライン
プログラムサービスには多分インストールされていなくて動作しないんじゃないかなともいます
上下前次1-新書関写板覧索設栞歴
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル
ぬこの手 ぬこTOP 1.644s*