プログラミングのお題スレ Part16
■ このスレッドは過去ログ倉庫に格納されています
[お題] 今月(2019/12)の13日は金曜日。 開始年月と終了年月が与えられる。年は西暦、年月区切りは"/"。 開始年月一日から終了年月末日の間で"13日の金曜日"は何回あるか。 現在のグレゴリオ歴ルールで、終了年月末日まで変わらないとする。 制約: 1970 <= 年 <= 300億, 1 <= 月 <= 12, 開始年月 <= 終了年月 1) 2019/1 2019/12 --> 2 // 今年は9月と12月が該当 2) 1980/1 2012/12 --> 57 3) 213456/8 453212/4 --> 412380 4) 2000/1 2399/12 -->? 5) 2000/11 2800/9 -->? 6) 123456789/11 7301177081/10 -->? 7) 1970/1 30000000000/12 --> 51599996613 ※数十万年程度だと力技だけで回っちゃうので、難易度調整で300億に。 wikiの"グレゴリオ歴#暦法" https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AC%E3%82%B4%E3%83%AA%E3%82%AA%E6%9A%A6#%E6%9A%A6%E6%B3%95 300億にしても年の曜日は14パターンしか無いのであっという間に解ける気が… 曜日は400年周期だから400年分求めればあとは割り算するだけかな? >>288 ずるいやり方だが、取り敢えずPowerShellに 1..12 |? {([DateTime]"2000/$_/13").DayOfWeek -eq "Friday"} 1..12 |? {([DateTime]"2400/$_/13").DayOfWeek -eq "Friday"} と打ち込んでみると、 10 10 と表示され、2000年と2400年の13日の金曜日は10月で一致する。 これと閏年調整のパターンが400年周期であることを組み合わせると、 13日の金曜日の出現パターンも400年周期になることが分かる。 だから、400年分の表を作ってしまえば、遅いPowerShellでも余裕で解ける。 https://ideone.com/oV7JFk --- 実行結果 --- 2019/1 2019/12 -> 2 1980/1 2012/12 -> 57 213456/8 453212/4 -> 412380 2000/1 2399/12 -> 688 2000/11 2800/9 -> 1375 123456789/11 7301177081/10 -> 12345678901 1970/1 30000000000/12 -> 51599996613 >>285 正解。例によってRで簡潔に書いた解答例: https://ideone.com/RhEtiC >>287 やっぱり無理か。ちなみに、Juliaでz = 12345まで力任せで求めるプログラム https://ideone.com/iqMYLa --- 実行結果 --- 階乗の0である桁が1個になる最小値は5です。 階乗の0である桁が12個になる最小値は37です。 階乗の0である桁が123個になる最小値は299です。 階乗の0である桁が1234個になる最小値は2414です。 階乗の0である桁が12345個になる最小値は20177です。 >>293 >>287 の式に20177を入れると12349.7 かなりいい線行ってる 123457桁になる 30484! から 下位に0が123457個続く 493840! までの間に存在しない事を示せば 存在しない証明になりますが もっと範囲を絞った証明は出来ないですかねえ 確率的には>>287 の付近だけ調べれば良いんですが... 全部調べる感じでぶん回してるけど1234567までが長いお(´・ω・`) (123456は>>295 の言う通り出なかった) 1時間ぶん回して900000!まで行ったが… 下限の n! を計算するのは速い そこから順番に1個ずつnを増やしていって 0を数えていかないとならない 見つからなければ上限までずっと ワープ (* 4 1234567) 4938268 (/ 4938268 5.0) 987653.6 (/ 987653 5.0) 197530.6 (/ 197530 5.0) 39506.0 (/ 39506 5.0) 7901.2 (/ 7901 5.0) 1580.2 (/ 1580 5.0) 316.0 (/ 316 5.0) 63.2 (/ 63 5.0) 12.6 (/ 12 5.0) 2.4 (+ 987653 197530 39506 7901 1580 316 63 12 2) 1234563 >>305 だからそれは>>282 の(A)の話じゃろ… 階乗の0である桁が1234567個になる最小値は1542987です。 お、出た…4時間か お題: 目覚まし時計の現在時刻とアラーム時刻が入力されるので、待機時間を出力しなさい 例: 現在時刻 = 10:00 アラーム時刻 = 16:00 待機時間 = 06:00 現在時刻 = 22:00 アラーム時刻 = 04:00 待機時間 = 06:00 >>309 この手の処理はPowerShellが得意だな。 function WaitingTime($now, $alarm) { $wait = [DateTime]$alarm - [DateTime]$now if ($wait -lt 0) {$wait += [TimeSpan]"12:00" + [TimeSpan]"12:00"} "現在時刻 = $now" "アラーム時刻 = $alarm" "待機時刻 = $wait" "" } WaitingTime 10:00 16:00 WaitingTime 22:00 4:00 WaitingTime 12:34:56 1:23:45 --- 実行結果 --- 現在時刻 = 10:00 アラーム時刻 = 16:00 待機時刻 = 06:00:00 現在時刻 = 22:00 アラーム時刻 = 4:00 待機時刻 = 06:00:00 現在時刻 = 12:34:56 アラーム時刻 = 1:23:45 待機時刻 = 12:48:49 お題: あなたは研究所で助手をしています ある日、博士からこんな手紙が届きました 助手よ。この数値の名前を教えて欲しい 16776960 あなたは博士に返事を書こうと思います その返事の内容をお答えください お題 与えられた自然数の0を全て右端に寄せる 例 2019 -> 2190 102030 -> 123000 123 -> 123 >>309 Ruby で、 require 'active_support/time' def calculate_time_span( now, alarm ) current = Time.now now_time = Time.parse( now, current ) #=> 2019-12-15 22:00:00 +0900 alarm_time = Time.parse( alarm, current ) #=> 2019-12-15 04:00:00 +0900 diff_time = alarm_time - now_time # アラームが翌日の場合 diff_time = alarm_time.tomorrow - now_time if diff_time < 0 Time.at( diff_time ).utc.strftime( '%H:%M' ) end inputs = %w(10:00 16:00 22:00 04:00) # (現在時刻, アラーム時刻)の組 inputs.each_slice( 2 ) do |now, alarm| # 2個ずつ処理する puts calculate_time_span( now, alarm ) end >>309 Ruby def waitTime( n, a ) Time.at( (a - n) % 86400 ).utc end >>317 これもPowerShellで簡単。 function f($n) { $m = -join([char[]]"$n" |? {$_ -ne "0"}) ($m += "0" * ("$n".length - $m.length)) } f 2019; f 102030; f 123 お題:ハノイの塔の最少手数は一種類しかないのか? (Part 13, 055) 結果:n枚の円盤すべてを移動させるには最低 2^n −1 回の手数がかかる。 4ピンのハノイの塔(河内塔) n枚の円盤は最初ピン0にある。n枚すべてをピン3に移動させる。 条件: 小円盤の上に大円盤を載せられない。 ピン1とピン2には最大1枚しか置けない。 ・n=2 のとき 12, -, -, - 2, 1, -, - -, 1, -, 2 -, -, -, 12 (3手) ・n=3 のとき 123, -, -, - 23, 1, -, - 3, 1, 2, - -, 1, 2, 3 -, 1, -, 23 -, -, -, 123 (5手) ・n=4 のとき 1234, -, -, - 234, 1, -, - 34, 1, 2, - 4, 1, 2, 3 4, 1, -, 23 -, 1, 4, 23 2, 1, 4, 3 12, -, 4, 3 12, 3, 4, - 12, 3, -, 4 12, -, -, 34 2, 1, -, 34 -, 1, -, 234 -, -, -, 1234 (13手) ・n=5 のとき 12345, -, -, - 2345, 1, -, - 345, 1, 2, - 45, 1, 2, 3 45, 1, -, 23 45, -, -, 123 5, 4, -, 123 -, 4, 5, 123 4, -, 5, 123 4, 1, 5, 23 24, 1, 5, 3 124, -, 5, 3 124, 3, 5, - 124, 3, -, 5 24, 3, 1, 5 4, 3, 1, 25 4, 3, -, 125 -, 3, 4, 125 3, -, 4, 125 3, 1, 4, 25 23, 1, 4, 5 23, 1, -, 45 3, 1, 2, 45 -, 1, 2, 345 -, 1, -, 2345 -, -, -, 12345 (25手) お題: ここに単語を登録したリストがある リストには以下の種類の言葉が存在する 単語:(例)くさり 単語解説:(例)環状の部品を繋げて線状にしたもの リストには上記ペアを1単位として、ずらずら並んでいる (数十個くらい) リストの中の似たような単語を探し、 以下のサンプルのようにボケ、ツッコミを繰り返すプログラムを作れ 似たような単語が見つからない場合には 最後に「こうじ:お前とはもうやってられませんわ」とprintし、 プログラムを終了せよ 動作サンプル: こうじ:「くさび」を見ると興奮するよね てつお:ああ、環状の部品を繋げて線状にしたものね こうじ:それは「くさり」 てつお:ああ、マルスダレガイ科に属する二枚貝ね こうじ:それは「あさり」 てつお:ああ、慰安婦の嘘を書いた新聞ね こうじ:それは「あさひ」 こうじ:お前とはもうやってられませんわ >>326 ・n≧6のとき ピン1とピン2には各1個しか置けないから 1〜(n-1) を置くことはできない。 ∴ n を ピン0 から ピン3 に直送することはできない。 ∴ ピン0 → ピン1 → ピン3 と送ろう。 まず 12345 をピン2、ピン3に退避する。(n=6の場合) 123456, -, -, - 6, -, m, 12345-m (1≦m≦5) 6, -, -, 12345 は m=1 と見なす。 -, 6, m, 12345-m 次にピン3を空けるため、ピン0とピン2に移すことになる。 しかしピン0には3枚しか移動できず、ピン3に n-5枚残ってしまう。 ∴ n≧6 では不可能。 条件を変えたらどうなるか? 条件(1,1) ピン1、ピン2には最大で1枚しか置けない。 >>326 条件(1,2) ピン1には最大で1枚、ピン2には最大で2枚しか置けない。 条件(2,2) ピン1、ピン2には最大で2枚しか置けない。 >>331 pin1,pin2に置ける枚数(の合計)に上限があれば 移動可能枚数に上限がつく >>314 common lisp (format t "~R" 16776960) sixteen million, seven hundred and seventy-six thousand, nine hundred and sixty >>317 perl5 cat digits 2019 102030 123 cat digits | perl -lane '$zero = 0; while (s/0//) {++$zero}; print $_ . "0" x $zero;' 2190 123000 123 >>317 Ruby def f(n) n.to_s.chars.partition{|x| x !="0"}.join .to_i end >>326 これ昔やったことがありますが、すっかり忘れてしまったのは残念ですね… >>317 PowerShell function f($n) {($n -replace "0", "") + ($n -replace "[^0]", "")} >>317 julia function f(n) r = "" for c = reverse(string(n)) if c == '0' r = r * c else r = c * r end end parse(Int, r) end お題 任意の文字列からaが連続する最も長い長さを出力してください 入力:acgtaattgaaagggtctt 期待値:3 >>341 Ruby p 'acgtaattgaaagggtctt'.gsub(/[^a]+/,' ').split.uniq.sort_by{|s| s.size}.last.size お題 1〜1,000 の整数の内、3 か5 の倍数だけを選んで、その合計を求めよ >>346 Rで2通りの求め方 d <- c(3, 5, -3 * 5) q <- 1000 %/% d cat(sum(d * q * (q + 1) / 2), "\n") cat(sum(which(1:1000 %% 3 == 0 | 1:1000 %% 5 == 0)), "\n") --- 実行結果 --- 234168 234168 >>341 Ruby p 'acgtaattgaaagggtctt'.scan(/a+/).max.size # => 3 >>346 Ruby p 0.step(1000,3).sum + 0.step(1000, 5).sum - 0.step(1000, 15).sum # => 234168 お題:ファイル名の一部に空白文字が使える OS(出題者想定は Windows7) の元で、正常に argc, argv を切り出せるスタートアップ支援ルーチンを作ってください "" で囲まれている文字列は、それが一つのファイル名またはディレクトリ名として扱うこととし、"" で囲まれていない空白は引数の区切りとします int main() { rearrange(...); ... と main の頭に置いて、xargc, xargv を代わりに使う、見たいな感じでお願いします 例によって私が痛切に欲しいと思っているものです… >>341 は簡単すぎるので、 任意の文字列から連続してる文字が最も長い文字とその文字数を求めよ 最も長い文字が複数ある場合は全て出力すること 入力:acgtaattgaaagggtctt 期待値: ("a", 3), ("g",3) >>346 C int s(int n){ return (1000/n)*(1000/n+1)/2*n; } int main(){ return s(3)+s(5)-s(15); } int main(){ return 234168; } で良い気がしてきた >>351 Ruby p 'acgtaattgaaagggtctt'.scan(/((.)\2*)/).group_by{|s, _| s.size}.max&.last&.map{|s, c| [c, s.size]} # => [["a", 3], ["g", 3]] acgtが出てくんだからながさ1億の文字列なんじゃね acgtが出てくんだからDNA配列だろな。 a=adenine, c=cytosine, g=guanine, t=thymine ながさ30億の塩基対なんぢゃね?(ヒトの場合) >>331 ・n=7 のとき 条件(1,2) または 条件(2,2) とする。 1234567, -, -, - (>328) 67, -, -, 12345 7, 6, -, 12345 -, 6, 7, 12345 6, -, 7, 12345 (>327) 12346, -, 7, 5 12346, 5, 7, - 12346, 5, -, 7 12346, -, 5, 7 (>327) 6, -, 5, 12347 6, 5, -, 12347 -, 5, 6, 12347 5, -, 6, 12347 (>327) 12345, -, 6, 7 12345, -, -, 67 (>328) -, -, -, 1234567 にて可能。 (1,2)で8 (2,2)だと12 までは出来たぞ (1,3)で11 紙と鉛筆で考えただけなんで もっと出来るかも (n,1)=3n+2 (2,2)以上だと (m, n)=4(n+m-1) まではいける >>331 ・n=8のとき 条件(1,2) または 条件(2,2) とする。 12345678, -, -, - (>328) 678, -, -, 12345 78, -, 6, 12345 (>328) 1234578, -, 6, - 1234578, -, -, 6 (>328) 78, -, -, 123456 8, 7, -, 123456 -, 7, 8, 123456 7, -, 8, 123456 (>328) 123457, -, 8, 6 123457, 6, 8, - 123457, 6, -, 8 123457, -, 6, 8 (>328) 7, -, 6, 123458 7, 6, -, 123458 -, 6, 7, 123458 6, -, 7, 123458 (>328) 123456, -, 7, 8 123456, -, -, 78 (>328) 6, -, -, 1234578 -, -, 6, 1234578 (>328) 12345, -, 6, 78 12345, -, -, 678 (>328) -, -, -, 12345678 にて可能。 ・n=9 は 条件(1,2) では無理か・・・・ (0,0)=1 (n,m)=(n+2)(m+2)-4 ですかね >>359 Rでrle関数を使って楽々 MaxRepChar <- function(s) { if (!nchar(s)) return(invisible()) r <- rle(unlist(strsplit(s, ""))) b <- r$lengths == max(r$lengths) cat(sprintf('("%s", %d)', r$values[b], r$lengths[b]), sep = ", "); cat("\n") } MaxRepChar("acgtaattgaaagggtctt") MaxRepChar("http://mevius.5ch.net/test/read.cgi/tech/1573948822/" ;) -- 実行結果 -- ("a", 3), ("g", 3) ("t", 2), ("/", 2), ("8", 2), ("2", 2) f(m, n) : 動かせる最大枚数 m≧n≧1の時 x=f(m-1,n) A:1,2,3,...,x B:x+1,...,x+n C:x+n+1 D:x+n+2 ABCD, -, -, - CD, -, -, AB C, D, -, AB AC, D, -, B AC, -, -, BD C, -, - ABD -, C, -, ABD A, C, -, BD A, -, -, BCD -, -, - ABCD よって f(m, n)≧f(m-1,n)+n+2 f(1,0)=2 f(m,n)=f(n,m) と数学的帰納法により f(m,n)≧(m+2)(n+2)-4 >>371 理論はどうでもいいから動くコードを出して欲しいです、このスレ的には >>317 文言 wenyan-lang http://wenyan-lang.lingdong.works/ide.html 吾有一術。名之曰「零右寄」。欲行是術。必先得一數。曰「数」。乃行是術曰。 吾有三數。曰零。曰零。曰一。名之曰「甲」曰「乙」曰「丙」。 恆為是。若「数」等於零者乃止也。除「数」以十。所餘幾何。昔之「甲」者。今其是矣。 若「甲」等於零者。乘「乙」以十。昔之「乙」者。今其是矣。若非。乘「甲」以「丙」。 加其以「乙」。昔之「乙」者。今其是矣。也。除「数」以十。昔之「数」者。今其是矣。 除其以一。所餘幾何。減「数」以其。昔之「数」者。今其是矣。 乘「丙」以十。昔之「丙」者。今其是矣。云云。乃得「乙」。是謂「零右寄」之術也。 吾有一列。名之曰「丁」。充「丁」以二千零一十九。以一十萬二千零三十。以一百二十三。 凡「丁」中之「戊」。施「零右寄」於「戊」。名之曰「己」吾有三數。曰「戊」。曰「「、」」。曰「己」。書之。云云。 OUTPUT --------------------- 二千零一十九、二千一百九十 一十萬二千零三十、一十二萬三千 一百二十三、一百二十三 なんかGIGAZINEで紹介されていたので >>363 ・n=7 のとき 条件(1,2) または 条件(2,2) {1234}=A と略記する。 A567, -, -, - (>327) 567, -, -, A 67, 5, -, A 7, 5, 6, A 57, -, 6, A (>327) A57, -, 6, - A57, -, -, 6 (>327) 57, -, -, A6 7, 5, -, A6 -, 5, 7, A6 5, -, 7, A6 (>327) A5, -, 7, 6 A5, 6, 7, - A5, 6, -, 7 A5, -, -, 67 (>327) 5, -, -, A67 -, -, 5, A67 (>327) A, -, 5, 67 A, -, -, 567 (>327) -, -, -, A567 にて可能。 >>368 ・n=8のとき 条件(1,2) または 条件(2,2) {12345} = A と略記する。 A678, -, -, - (>328) 678, -, -, A 78, 6, -, A 8, 6, 7, A 68, -, 7, A (>328) A68, -, 7, - A68, -, -, 7 (>328) 68, -, -, A7 8, 6, -, A7 -, 6, 8, A7 6, -, 8, A7 (>328) A6, -, 8, 7 A6, 7, 8, - A6, 7, -, 8 A6, -, -, 78 (>328) 6, -, -, A78 -, -, 6, A78 (>328) A, -, 6, 78 A, -, -, 678 (>328) -, -, -, A678 にて可能。 ・n=12 のとき 条件(2,2) {12345678} = A, {9,10} = B, 11=C, 12=D と略記する。 ABCD, -, -, - (>376) BCD, -, -, A CD, -, B, A D, C, B, A BD, C, -, A (>376) ABD, C, -, - ABD, -, -, C (>376) BD, -, -, AC D, -, B, AC -, D, B, AC B, D, -, AC (>376) AB, D, -, C AB, D, C, - AB, -, C, D AB, -, -, CD (>376) B, -, -, ACD O, 9, -, ACD (>376) AO, 9, -, CD AO, -, -, 9CD (>376) O, -, -, A9CD -, O, -, A9CD (>376) A, O, -, 9CD A, O, 9, CD A, -, 9, OCD A, -,-, BCD (>376) -, -, -, ABCD にて可能。 >>317 J f =: 3 : 0 a =. ": y b =. a -. '0' ". b , a -. b ) >>346 Ruby で、234,168 # 蓄積変数の初期値は、0 puts ( 1..1_000 ).inject( 0 ) { |sum, num| num % 3 == 0 || num % 5 == 0 ? sum + num : sum } >>375-377 >>371 で理論は出来たんだから 次は プログラムにするか 等号の証明をするか 最短手順を調べるか 本数を増やすか ではないでしょうか? 私は>>371 で満足 出題者ありがとう お題 MY FAVORITE SONGS を、Snake, Camel, Pascal にして! my_favorite_songs, myFavoriteSongs, MyFavoriteSongs >>346 Kotlin script ただ馬鹿正直に抜き出して足すだけ。 println((1..1000).filter { it % 3 == 0 || it % 5 == 0 }.sum()) >>383 Ruby str = 'MY FAVORITE SONGS' puts str.tr('A-Z ', 'a-z_') # => my_favorite_songs puts str.gsub(/ (\w)/){$1.downcase}.swapcase # => myFavoriteSongs puts str.split.map(&:capitalize).join # => MyFavoriteSongs >>351 >>362 Common Lisp https://ideone.com/hTxKo6 30億バイトでの実行結果: % uname -p Intel(R) Core(TM) i7-4765T CPU @ 2.00GHz % /usr/bin/time -p sbcl --script odai-pt16-351-362-lisp-3-hash-table.lisp </tmp/random-acgt-3-billion.txt ((#\T . 17)) real 178.75 user 177.55 sys 1.17 % *standard-input* ではなく (open "/dev/stdin" ...) を使っているのは *standard-input* が遅いから ざっと六倍もの時間がかかった ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる