プログラミングを学習中に理解できずに悩んでしまいましたどなたかお願いします。
a, b, c, d のみで構成された文字列 S が与えられます。 文字列 S から 1 文字以下の文字の変更を行ったのち、文字の順番を並び替えることで作れる文字列を、危険なパスワードとします。 ただし、変更後の文字列も a, b, c, d のみで構成されているものとします。 全ての危険なパスワードを辞書順に列挙してください。
制約
1≤|S|≤3
S は a, b, c, d からなる
入力
入力は以下の形式で標準入力から与えられる。
S
出力
危険なパスワードを、一行に一個ずつ、辞書順に列挙せよ。
入力例
ab
出力例
aa
ab
ac
ad
ba
bb
bc
bd
ca
cb
da
db
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/04/25 08:41
2016/04/25 09:28
2016/04/25 13:20
回答3件
0
こんにちは。
情報の追加・修正欄では狭いので、こちらから。
プログラミングを学習中に理解できずに悩んでしまいましたどなたかお願いします。
何を「お願い」したいのか、整理された方がよいと思います。
プログラムを教えて欲しい、アルゴリズムを教えてほしいでは「丸投げ」になります。
どこが分からないのか、整理下さい。
ところで、そもそも問題文がかなり曖昧です。
|S|
の意味を記載下さい。文字列Sの文字数のような印象ですが、その通りですか?
入力は以下の形式で標準入力から与えられる。
S
M
入力例
ab
M
はどこに行ったのでしょうか?
出力
S に M 回操作を行って得られる文字列を出力せよ。
1回
の操作がどのような操作か未定義です。
投稿2016/04/25 08:41
総合スコア23272
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/04/25 08:47
2016/04/25 09:08
0
たぶん授業か何かの課題だと思いますが、こういうのは自分で考えないと、身につかないと思うのでヒントだけ。
Sは1文字から3文字までで、文字はa,b,c,dの4つでしょ。
どう求めるかですが、まず辞書順というのは、最後の出力の話なので検討は別で行います。
やり方の一つとして、入力された文字列の「文字数」から作ることのできる「全文字列」を列挙して、変更の条件に合うものだけ抜き出す方法が考えられます。(あわないものを削除するのでも同じこと)
条件というのは「変更文字が1文字以下」ということです。つまり、2文字なら2文字のうち少なくとも1文字は含まれていることが条件、3文字なら少なくともそのうちの2文字が含まれていることが条件になります。
問題文がわかりにくければわかるように言い換えてみればいいのです。
投稿2016/04/25 08:45
総合スコア3579
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/04/25 08:46 編集
2016/04/25 09:13
0
ベストアンサー
文字列の長さが2の場合で考えます。
2文字で構成される文字列の組み合わせは 4 ** 2 (= 16) 通りです。
0 .. 15 の数字に "aa", "ab", .. を割り当てることにします。(辞書順になる)
0 .. 15 の数字を 4 進数で表現したら、 0 -> a, 1 -> b, 2 -> c, 3 -> d に置換すれば、番号に相当する文字列を得ることができます。
00 -> aa
01 -> ab
02 -> ac
03 -> ad
...
33 -> dd
文字列が与えられたとき、[a の出現回数、b の出現回数, c の出現回数, d の出現回数] を得る処理を作成します。
2 つの文字列があたえられた時、それぞれの [a の出現回数、b の出現回数, c の出現回数, d の出現回数] を計算してから
対応する要素毎に引き算をすると [a の出現回数の変化, b の出現回数の変化, d の出現回数の変化, d の出現回数の変化]
を得ることができます。
これが [-1, 1, 0 , 0] のような場合は a を b にしたのだということがわかります。
このようにして 2 つも文字列が 1 文字お置換しただけの関係かをしらべることができます。
以上のことを踏まえ、ruby で記述してみたのが ↓です。
先頭にある S を変更してから走らせることで、回答を得られます。
ruby
1# S = 'a'.freeze # 入力文字列を設定する 2S = 'ab'.freeze # 入力文字列を設定する 3#S = 'dd'.freeze # 入力文字列を設定する 4# S = 'abc'.freeze # 入力文字列を設定する 5 6S_split = S.tr('abcd', '0123').split('').freeze 7S_counts = '0123'.split('').map { |x| S_split.find_all { |y| x == y }.size }.freeze 8DIFFS = [-1, 0, 0, 1].freeze 9FORMAT = "%0#{S.length}d".freeze 10 11# S から1文字以下の文字を変更して順番をかえたものであるかを調べる 12def checked(s) 13 split = s.split('') 14 # [a の出現回数, b の出現回数, c の出現回数, d の出現回数] の配列を得る 15 counts = '0123'.split('').map { |x| split.find_all { |y| x == y }.size } 16 # 文字のい入れ替えがないなら、 true を返す 17 return true if S_counts == counts 18 # [a の出現回数の変化, b の出現回数の変化, c の出現回数の変化, d の出現回数の変化] を得る 19 diffs = (0..counts.size - 1).map { |i| S_counts[i] - counts[i] } 20 # 一文字も入れ替えになっているなら true を返す 21 diffs.sort == DIFFS 22end 23 24if S.length == 1 25 'abcd'.split('').map { |x| puts "#{x}" } 26else 27 # S の長さが 2 なら 00 .. 15 までループする。 28 # 00 は "aa", 01 = 'ab', .... も対応させる。 29 # (数字を 4 進数で表記して、0 -> a, 1 -> b, 2 -> c, 3 -> d に対応をさせる) 30 (0..(4 ** S.length - 1)).each do |x| 31 s = format(FORMAT, x.to_s(4).to_i) 32 puts s.tr('0123', 'abcd') if checked(s) 33 end 34end
実行結果
S = "a" の場合 a b c d S = "ab" の場合 aa ab ac ad ba bb bc bd ca cb da db S = "dd" の場合 ad bd cd da db dc dd
ruby が分かるなら、これを C/CLL に書き換えるとよいと思います。
rby がからないなら、考え方を C/C++ で書き下せばよいとおもいます。
(上の考えは、計算量の観点では問題があります。
是非 もっとよい考え方をみつけて、それをプログラムに落としてみてください)
投稿2016/04/25 15:54
編集2016/04/25 21:18総合スコア22324
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。