質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

9回答

1916閲覧

プログラムを書く前の考え方を知りたい。言語は不問です。

Bafetto

総合スコア22

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

4クリップ

投稿2018/12/30 15:13

編集2018/12/31 00:51

たとえば以下のような問題があったとします。
※ただし動物の名前は、今後増える可能性があります。例えば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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tanat

2018/12/30 15:31

(質問に至った背景はどうあれ)現状では「やってほしいことを丸投げした質問」「」に該当するとしか思えないので、「最初に何を考え・次に何を考え・最後に何を考えてコードを書くのでしょうか?」について自分なりにどう考えて、何に躓いているかを追記すると適切な回答がつくと思います。
fu7mu4

2018/12/31 02:37

仕様として動物名に空白文字が含まれるか、含まれる場合はどのように表記するかを決定してください。また入力文字はASCIIの表示可能文字の範囲か、それともSHIFT-JISの範囲か、またはUNICODEも可能かといったことも検討材料です。
guest

回答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
Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2018/12/30 15:27 編集

プログラミング言語の場合はメモ帳の代わりに線形リストを使います。格納するのは名前と数字なので構造体やクラスやタプルのリストにします。 または名前をキーにした連想配列を使います。
guest

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
hichon

総合スコア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

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Bafetto

2019/01/03 08:54

d[word] += 1を基本形に戻すとd[word]=d[word]+1ですよね?もっと基本形に戻すことできますか?d[word]がよくわかりません。 >>> word_list ['cow', 'bear', 'cow', 'wolf', 'bear', 'wolf', 'bear'] # word_listの内容 d = dict() #空の辞書を作る for word in word_list: #word_listの単語をwordに入れる if word in d #空の辞書の中にwordに入れられた単語があったらTure d[word] += 1 ?の状態になっています。空の辞書が[]リストに何をしているのでしょうか?
hayataka2049

2019/01/03 12:28

[]はリストではなく添字表記です。また、else節でキーと値を初期化しているので空の辞書ではありません。 考え方以前に基本的な構文と言語仕様を学んでください。
Bafetto

2019/01/05 11:57

添字を学習しました。私の添字のイメージは以下の感じでした。 s = "string" s[0] "s" なので「添字とは整数である」と思っていました。リストの要素も添字になるという理解でいいんですよね?。 質問 ① >else節でキーと値を初期化している とあるのですが、初期化しているとわかる目印があるのでしょか?d[word] += 1ように記述すると自動的に初期化することになるのでしょうか? 初期化とは、辞書の値に0が入るということなのでしょうか? ② >if word in d: 上記コードに関してなのですが、上記コードの意味は「もしdの中にwordがあったらtrue」だと思っています。しかしこの時点では、dは空の辞書なので永久にfalseになると思ってしまいます。なぜtrueになるのでしょうか? ③私は「わかるpython」という本を読んでいます。説明の中に辞書は、添字(インデクス)を使用できないとあります。この場合はなぜ使用できるのでしょうか? ④hayataka2049推薦の書籍ってありますでしょうか?
hayataka2049

2019/01/06 09:59 編集

>① >else節でキーと値を初期化している >とあるのですが、初期化しているとわかる目印があるのでしょか?d[word] += 1ように記述すると自動的に初期化することになるのでしょうか? >初期化とは、辞書の値に0が入るということなのでしょうか? d[word] = 1が初期化に相当します。念のために言っておきますが、便宜的に初期化と言っているだけで、実際は辞書のwordというキーに1という値をセットしているだけです。 >② >if word in d: >上記コードに関してなのですが、上記コードの意味は「もしdの中にwordがあったらtrue」だと思っています。しかしこの時点では、dは空の辞書なので永久にfalseになると思ってしまいます。なぜtrueになるのでしょうか? d[word] = 1が実行された以後はキーと値が追加されるのでTrueになります。 >なので「添字とは整数である」と思っていました。 >③私は「わかるpython」という本を読んでいます。説明の中に辞書は、添字(インデクス)を使用できないとあります。この場合はなぜ使用できるのでしょうか? その本の説明が間違っているか、間違って理解しています。数字のインデックスを使うか使わないかに関わらずpythonでは subscription ::= primary "[" expression_list "]" のような構文表記であらわされるものを添字表記と呼ぶと公式に定義されています。 https://docs.python.jp/3/reference/expressions.html#subscriptions なので辞書等であっても添字表記と呼称します。 >④hayataka2049推薦の書籍ってありますでしょうか? 正直あまりないのですが、読むなら下手な書籍よりは公式のチュートリアルなどを勧めます。 https://docs.python.jp/3/tutorial/ また、オライリーの入門Python3なども良いでしょう(分厚いけど)。
guest

0

まず、使うプログラミング言語で、ハッシュ(Pythonだと辞書)が使えるかどうか。
使える場合は簡単で、単語をキー、カウンタを値とするハッシュで数えます。

使えない場合は、配列を使うことになります。
単純には、単語とカウンタを要素とする配列を作って、カウントしていきます。
データ数が膨大で配列から同じ単語を探す部分の速度向上が必要な場合は、配列の上に自分でハッシュを構築するなどします。

投稿2018/12/30 15:31

otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

最初に何を考え

入力と出力の関係性を示す「仕様」が定義されているか探します。

次に何を考え

入力と出力の関係性を示す「仕様」が定義されていないことがわかるので、出力のみ考えれば良いことに気が付きます。

最後に何を考えてコードを書く

cow 2 wolf 2  bear 3

おかしなところにホワイトスペースがあるようなので、出力の仕様を違えないように気をつけて出力します。

投稿2018/12/30 15:32

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

実務においてこのような課題に対処するとなると、大体次のような感じでしょうかね。このくらい単純なら特段意識的に作戦を考えるまでもなく、いきなりワンライナーを書き始めてしまうと思いますが、しいて丁寧に手順を追うなら:

  1. まず対象データをよく観察する。
  2. どんな出力が必要確認する。
  3. 使う言語と大体の作戦を考える。
  4. 実際に書いてみて多少の試行錯誤。

まず入力されるべきデータの観察。データがテキストで、スペースで区切られた単語のリストである、となります。
次に出力。出力すべき内容は入力された単語とその頻度。これを単語・スペース・頻度・改行の順に出力していけばいいとなります。
言語と作戦。まあこういう対象だと、私なら9割がたperl。問題が単純なので今回はawkでいいでしょう。作戦としては、

  1. 入力データの単語への分割
  2. 単語ごとの数え上げ
  3. 最後に出力

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

KojiDoi

総合スコア13669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

サイト 解き方 はいかがでしょうか?

簡単に言えば、大筋は質問者さんに同じで、
でも、質問者さんの場合はライブラリの使い方がわかっていないだけだと思います。

Zuishinさんがお書きになっているように、言葉をお借りすると

len の使い方を知らないからです。len が何の長さを測るものか知っていればそこで len を使おうとは思わなかったでしょうし、すぐに別の方法を探したでしょう。

(中略)
つまり、頭の回転とか発想の仕方ではなく、あなたに足りないのはライブラリの知識です。

ですね。

len関数は言語がわかりませんが、VBAでもほかの言語でも "文字列全体の長さ" を取得するためのものです。
そうなると質問での、自分が欲しいデータじゃない...ってことになります。


[追記1]

ライブラリ( 関数, クラス等のいわゆる API? ) はその言語(もしくはそのライブラリの)documentation (ヘルプファイルとかリファレンス的なもの. MSDNとかそういうの.) を参照します。

投稿2018/12/31 01:35

編集2018/12/31 03:55
BeatStar

総合スコア4958

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Bafetto

2018/12/31 03:47

ありがとうございます。こうゆう説明がほしかったんです。
Zuishin

2018/12/31 04:07

> まず、丸投げしないでください。 > 丸投げしても実力がつきません。 > なので自分で考えて組んでみましょう。 しっかり参考にしてください。 冒頭に何よりも真っ先に書いてある大事なところです。
BeatStar

2018/12/31 05:56 編集

>> しっかり参考にしてください。 えーっと、Zuishinさん、 私にですか? (混乱) もしかして言葉をお借りしたことでしょうか?
Zuishin

2018/12/31 06:05

質問者さんにです。リンク先の情報はそれがすべてであるように私には読めます。
BeatStar

2018/12/31 06:22

Zuishinさん あ、そっちですか。 了解しました。(安堵)
guest

0

大前提

そもそもプログラムを書く必要があるか?
すでにその問題をとく方法が存在していないか?
自分で書かずに、他人に頼んだほうがよいか?

入力・出力の仕様

cow bear cow wolf bear wolf bear
はどのようにあたえられるのか?
テキストファイル? プログラム中での配列? ...
単語の定義は? 大文字・小文字の区別?

出力はコンソール? ファイル? 出力形式は
出力順次は単語の辞書順、出力結果の昇順・降順?

内部でつかうデータ構造/利用する機能・ライブラリー

動作確認・テストケース

単語リストが空の場合

類似問題に関する情報

自分の頭のなかの知識
web 上での検索

追記:

... プログラムを書く前の考え方 ...

大切なのは、プログラムを書いた後のほうです。
書い後に実行させる前の見直し、実行させてみた上でのバグ修正、速度計測 そして、プログラム改善です。

投稿2018/12/30 21:02

編集2019/01/05 05:47
katoy

総合スコア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
Karasuryu

総合スコア52

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Bafetto

2019/01/06 02:12

解答ありがとうございます。今までで1番シンプルです。頭の中やググルなどプロセスがあってわかりやすいです。しかし「'%s %d'%」が理解できません。%は演算子ですか? sとdはどこから来たのですか?もう少し詳しくお願いできないでしょうか?
Karasuryu

2019/01/06 08:49

%sや%dは変換指定子などと呼ばれ、C言語などいろいろな言語で使われている記号です。%sはstringすなわち文字列、%dはdecimalすなわち10進数の整数を意味しています。ここでは%s, %dそれぞれに当たるものは%(word, words.count(word))の中のwordとwords.count(word)です。wordは文字列、words.count(word)はwordsリストの中のwordに当たる単語の数を整数で返すメソッドです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問