たとえば以下のような問題があったとします。
※ただし動物の名前は、今後増える可能性があります。例えばape zebra tiger等が複数加わる可能性があります。
cow bear cow wolf bear wolf bear
を
cow 2
wolf 2
bear 3
のように出力したい時、最初に何を考え・次に何を考え・最後に何を考えてコードを書くのでしょうか?できるだけ、頭の中の様子を詳しく教えて下さい。標準的な考え方があったら知りたいです。効率的なコードではなく、初心者がわかるようなとりあえず動くレベルがいいです。コードではなく、抽象的なレベルを希望。
追加
私が考えたこと。
問題とは現状とあるべき姿の差なんだそうです。今回の場合、問題はcow bear cow wolf bear wolf bearの数を数えて表現方法を変える。あるべき姿は、
cow 2
wolf 2
bear 3
です。
この差を埋めるために、どんな作業があればよいのかと思いました。見た目から3つあると思いました。1つ目は単語の数を数える。2つ目は同一単語は一つにまとめる。3つ目は縦に表示するの3つです。
1つ目の単語の数を数えるは、どうすればよいのかと思った時に頭に浮かんだのがlen関数でした。そこで以下のようなコードをとりあえず書いてみました。
line = input()
line1 = len(line)
print(line1)
解答は32で単語を数えず、要素数を数えていました。ここでストップしてしまいました。そこで思いつきではなく、考えてコードを書く方法があるのではないかと思い質問しました。このような状態の時、普通の人は次に何をするのでしょうか?文法の入門書を読んでも、ヒントらしきものが見つかりません。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/12/31 02:37
回答9件
0
言語不問ということなので日本語で。
cow bear cow wolf bear wolf bear
まず cow なのでメモ帳を取り出し、cow と書いて一を書きます。
次に bear なので同じく bear と書いて一を書きます。
さらに cow ですが、cow は既に書いてあるので一に一画加えて丁に変えます。
これを最後まで続け、最終的に cow 丁、bear 下、wolf 丁が得られるので、丁、下を算用数字に直します。
追記
どういう意味の質問かよくわからなかったのですが、これは前の質問の続きですね。発想法を尋ねているのだと思います。
結論から言うと、すべての問題に対して最も効率の良い方法を機械的に発想する方法はありませんが、熟練することによって効率を高めることができます。
まずどうしたらその問題が解けるかを考え、その方法の実装を言語やライブラリに合わせて考えます。熟練したプログラマーはその際に無意識レベルでリファクタリングするので、突然魔法のような方法が閃いたように見えますが、これは閃きではなく論理的思考の賜物です。
慣れないうちは実際に動くコードを書き、それを言語やライブラリに実装されている機能を使って効率化できないかどうかを「リファレンスを見ながら」考えてみてください。
set を知っているかどうかで書けるコードは違ってきます。知ってはいても頭に浮かぶかどうかは使い慣れているかどうかによるでしょう。とにかくその場しのぎのコードを検索してコピペするのではなく、自分でリファレンスを読み、自分の頭で考えることが大事です。
そうして自分の使う言語にどのような機能や制限があり、自分の使うライブラリにどのようなクラスや関数が実装されているかという知識を蓄え、実際に使い慣れることで短時間でのリファクタリングが可能になります。
追記2
「私が考えたこと」を読みました。そこで止まったのは、len の使い方を知らないからです。len が何の長さを測るものか知っていればそこで len を使おうとは思わなかったでしょうし、すぐに別の方法を探したでしょう。
文法は必要最低限の知識です。これは知っていて当たり前のことで、実際にはそれだけでは足りません。実際に問題を解こうと思えば、与えられた環境で何ができて何ができないかを知る必要があります。
つまり、頭の回転とか発想の仕方ではなく、あなたに足りないのはライブラリの知識です。繰り返しになりますが、億劫がらずにライブラリリファレンスに目を通してください。
投稿2018/12/30 15:21
編集2018/12/31 00:59総合スコア28656
0
シェル芸脳の考え方
1.まずは一行ずつ処理できるように、trコマンドで複数行にします。
bash
1$ echo cow bear cow wolf bear wolf bear|tr ' ' '\n' 2cow 3bear 4cow 5wolf 6bear 7wolf 8bear
2.uniqコマンドは入力データがソートされている必要があるため、sortコマンドを通します。
bash
1$ echo cow bear cow wolf bear wolf bear|tr ' ' '\n'|sort 2bear 3bear 4bear 5cow 6cow 7wolf 8wolf
3.同じ単語をuniqコマンでカウントします。
bash
1$ echo cow bear cow wolf bear wolf bear|tr ' ' '\n'|sort|uniq -c 2 3 bear 3 2 cow 4 2 wolf
4.最後に列の並びをawkコマンドで入れ替えて完成です。
bash
1$ echo cow bear cow wolf bear wolf bear|tr ' ' '\n'|sort|uniq -c|awk '$0=$2" "$1' 2bear 3 3cow 2 4wolf 2
上記の例では単語の順番がソートされてしまうので、出現順を保存したいときは一寸複雑になります:-)
bash
1$ echo cow bear cow wolf bear wolf bear|tr ' ' '\n'|awk '{if(b[$1]){b[$1]++}else{a[i++]=$1;b[$1]=1}}END{for(i=0;i<length(a);i++){print a[i],b[a[i]]}}' 2cow 2 3bear 3 4wolf 2
投稿2018/12/31 02:40
編集2018/12/31 03:18総合スコア5737
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
とりあえず単語が要素の文字列のlist
にしよう、まで考えます。
pythonの場合は標準でcollections.Counterが使えて、一行で数え上げをやってくれます。使えるものは知っておくことも大切(質問の趣旨とは違うと思いますが)。
python
1>>> word_list = "cow bear cow wolf bear wolf bear".split() 2>>> word_list 3['cow', 'bear', 'cow', 'wolf', 'bear', 'wolf', 'bear'] 4>>> from collections import Counter 5>>> Counter(word_list) 6Counter({'bear': 3, 'cow': 2, 'wolf': 2})
自分で書く場合は、とりあえず回数を保持するdict
でも作るか、と考えます。この辺はほぼパターンなので、何かを考えた結果そう思う、ということはありません。こういう場面ではdict
を使うのが適当、と覚えているだけです。
あとは単語のリストをループしてキーの値を0から足し上げていけば良いのですが、特に何もしなければ辞書は空です。なのでループのときに要素が辞書のキーに登録されているかを見て、それが辞書のキーに登録されていなければ1を登録、されていれば現在の値+1を登録、みたいにやってみることにします。
(余談ですが、dict.setdefault
というこれの略記法や、collections.defaultdict
というデフォルト値を設定できる辞書もpythonには用意されています。知識は重要)
最終的にはこんな感じですかね。
python
1>>> d = dict() 2>>> for word in word_list: 3... if word in d: 4... d[word] += 1 5... else: 6... d[word] = 1 7... 8>>> d 9{'cow': 2, 'wolf': 2, 'bear': 3}
投稿2018/12/30 15:37
総合スコア30933
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/01/03 08:54
2019/01/03 12:28
2019/01/05 11:57
2019/01/06 09:59 編集
0
最初に何を考え
入力と出力の関係性を示す「仕様」が定義されているか探します。
次に何を考え
入力と出力の関係性を示す「仕様」が定義されていないことがわかるので、出力のみ考えれば良いことに気が付きます。
最後に何を考えてコードを書く
cow 2 wolf 2 bear 3
おかしなところにホワイトスペースがあるようなので、出力の仕様を違えないように気をつけて出力します。
投稿2018/12/30 15:32
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
実務においてこのような課題に対処するとなると、大体次のような感じでしょうかね。このくらい単純なら特段意識的に作戦を考えるまでもなく、いきなりワンライナーを書き始めてしまうと思いますが、しいて丁寧に手順を追うなら:
- まず対象データをよく観察する。
- どんな出力が必要確認する。
- 使う言語と大体の作戦を考える。
- 実際に書いてみて多少の試行錯誤。
まず入力されるべきデータの観察。データがテキストで、スペースで区切られた単語のリストである、となります。
次に出力。出力すべき内容は入力された単語とその頻度。これを単語・スペース・頻度・改行の順に出力していけばいいとなります。
言語と作戦。まあこういう対象だと、私なら9割がたperl。問題が単純なので今回はawkでいいでしょう。作戦としては、
- 入力データの単語への分割
- 単語ごとの数え上げ
- 最後に出力
awkならセパレータを設定すれば1は勝手にやってくれる。2は配列を使えばよい。3はEND節を作ってforループを回せばいいと理解できます。最終的にはこんな感じか。
awk 'BEGIN{RS="[ \n]"}{n[$0]++}END{for(i in n){print i,n[i]}}' input.txt
投稿2018/12/30 17:43
総合スコア13669
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
サイト 解き方 はいかがでしょうか?
簡単に言えば、大筋は質問者さんに同じで、
でも、質問者さんの場合はライブラリの使い方がわかっていないだけだと思います。
Zuishinさんがお書きになっているように、言葉をお借りすると
len の使い方を知らないからです。len が何の長さを測るものか知っていればそこで len を使おうとは思わなかったでしょうし、すぐに別の方法を探したでしょう。
(中略)
つまり、頭の回転とか発想の仕方ではなく、あなたに足りないのはライブラリの知識です。
ですね。
len関数は言語がわかりませんが、VBAでもほかの言語でも "文字列全体の長さ" を取得するためのものです。
そうなると質問での、自分が欲しいデータじゃない...ってことになります。
[追記1]
ライブラリ( 関数, クラス等のいわゆる API? ) はその言語(もしくはそのライブラリの)documentation (ヘルプファイルとかリファレンス的なもの. MSDNとかそういうの.) を参照します。
投稿2018/12/31 01:35
編集2018/12/31 03:55総合スコア4958
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/12/31 03:47
2018/12/31 04:07
2018/12/31 05:56 編集
2018/12/31 06:05
2018/12/31 06:22
0
大前提
そもそもプログラムを書く必要があるか?
すでにその問題をとく方法が存在していないか?
自分で書かずに、他人に頼んだほうがよいか?
入力・出力の仕様
cow bear cow wolf bear wolf bear
はどのようにあたえられるのか?
テキストファイル? プログラム中での配列? ...
単語の定義は? 大文字・小文字の区別?
出力はコンソール? ファイル? 出力形式は
出力順次は単語の辞書順、出力結果の昇順・降順?
内部でつかうデータ構造/利用する機能・ライブラリー
動作確認・テストケース
単語リストが空の場合
類似問題に関する情報
自分の頭のなかの知識
web 上での検索
追記:
... プログラムを書く前の考え方 ...
大切なのは、プログラムを書いた後のほうです。
書い後に実行させる前の見直し、実行させてみた上でのバグ修正、速度計測 そして、プログラム改善です。
投稿2018/12/30 21:02
編集2019/01/05 05:47総合スコア22324
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
Pythonのような高級言語を使うという前提で考えると、
まず私は(与えられた問題が、単語をスペースで区切った文字列とすれば)
「文字列を単語で区切ってリストにしよう」
と考え、次に
「リストの中の同じ要素をカウントする機能が用意されているはずだ」
と考え、ググります。
Pythonなら
words = text.split(' ')
のようにして文字列からリストを作れます。
そして
words.count('単語')
によってリスト内の要素をカウントできるので、リストの各要素にこれを使おうと思います。pythonは以下のようにfor文を書くことができるので、
for word in words: print('%s %d\n'%(word, words.count(word)))
などとして結果を出力します。
すると同じ単語の行がその個数分表示されることに気づくので、重複するものをなくしたリストを作りたいと考え、ググります。するとset()でset型にすることができるとわかるので
for word in set(words): print('%s %d\n'%(word, words.count(word)))
と書き換えます。
投稿2019/01/05 09:59
編集2019/01/06 08:53総合スコア52
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/01/06 02:12
2019/01/06 08:49
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。