Ken’s Learning Projects

色々なスキルや資格の取得を実践・展開します!

edXを利用して新しいスキルを習得する (Finance & Management- 002)

それでは Finance や Management 系のedXを始めたいと思います。まず始めるのがColumbia University によって提供されている "Introduction to Corporate Finance" です。説明によると、Columbia のMBAコースに入る学生の1年目に提供されるもののようです。以下コースの概要です。

 

 このコースについて

このコースでは、昔からある金融の概念やルールを理解し、それらを企業や債券、株式の評価にどのように適用できるかを学びます。

このコースでは、貨幣の時間的価値、資本コスト、資本予算を取り上げます。債券や株式の評価、NPVの計算、IRRの計算など、多くのプロセスでExcelを使用します。

このコースは、コロンビア大学ビジネススクールのMBA1年生全員が必修としているファイナンス入門コースで、ウォール街で活躍する次世代のマーケットリーダーを育成している世界的な講師が担当します。

様々なバックグラウンドを持つ参加者は、進化し続ける金融の舞台で活躍するための準備ができます。

 

学ぶ内容

  • あらゆる資産を評価する方法
  • 企業が検討している数多くのプロジェクトの中から、どのプロジェクトを取り出すかを決める
  • あらゆるプロジェクトのリターンを計算する
  • プロジェクトが付加する価値を計算する
  • 債券を評価し、その利回りを計算する
  • 簡単なモデルを使って株式を評価する(例:株式の公正価格を決定する)

 

シラバス

  • 貨幣の時間的価値と現在価値
  • 現在価値 正味現在価値と内部収益率の法則
  • 資本予算
  • 債券と株式の評価

 

Introduction とありますが、基本的な知識は必要です!と最初にでてきます。が、そこも心配ありません。ビデオによる追加資料のURLが添付されており、それを見ることで一定の知識を得ることができます。Khan Academy というところからのもので、その中で5個程度のビデオを受けるようにと指示されています。

 

やってみた感想

やってみてですが、オンデマンドのビデオにより授業が進むことは Python の時と変わりません。ただ、その長さが比較的短く、2-3分のものが多いです。これにも一長一短ありますが、少しずつやってミニテストができるので、やったことを忘れないで済みます。したがって、一つ一つ覚えながら進めることが可能です。

今回は Certificate を取得しないのでいっていますが、そうすると単元ごとにテストがありません。これは鍵のマークがついていて受けさせてもくれません。まあ、単元の中のミニテストはできるのでいいのですが、正直少し物足りません。もし自分がどれだけわかっているかをより理解したい方は Certificate を取るべきですが、少し高めです。

少しexcelを使用します。もちろん Numbers でも可能です。ここで面白かったのは、なかなか使わないであろう "NPV" なる関数を使用したりします。こんな Finance に特化した関数があるのかと驚きました。ちなみに "NPV" は "Net Present Value" の関数だそうです。
=NPV(rate, value1, [value2], [value3], ... ) のように使います。

全体としてですが、新しいことを英語で学びたい方にとってはいいと思います。正直、日本語では言えますが、英語でなんていうんだろうなんて言葉がかなり出てきます。また、難しさ的には簡単な方で、最初にやるのにもいいと思います。ただ、上記の通り少し物足りないところはあると思います。そこはいろんなコースを取ることでカバーしたいと思います。

 

 

f:id:KenSuzuki1:20210210210105p:plain

 

edXを利用して新しいスキルを習得する (Programming- 010:番外編3)

これまで書籍やedXにてPythonを学習してきましたが、それに加えてPyQというWebサービスにて加えて学習を進めました。今回は、そのPyQで学習した内容及び感想と、その他の学習方法との比較を記載します。

 

PyQで勉強した感想

PyQで学習できる内容は以下になります。かなり広範囲に学習できる項目があり、長期間にわたってできるものではあると思います。ただ、サブスクリプションであるがゆえに、だらだらと続けるのは費用対効果が薄くなります。学習する方からしたら、一気にやってしまう方がいいのですが、なかなか自身の学習スピードとの兼ね合いもありますので、そこは難しい部分であったように思います。

f:id:KenSuzuki1:20210412224451p:plain

PyQ - 学習できる内容

やって見て思ったのが、やはり全体としては「写経」によって学習するのが主であるということです。これは書籍で勉強した時も思ったのですが、一部脳死してても進められる部分があります。それに対し、edXでは、自分で考えさせる部分が多かったです。そこに関しては確実にedXが良いところではないかと思います。

ただ、上記のように広範囲であることはいい部分です。edXですと、まあ他のより上位のコースを取っていけばいいのですが、今回やったものだけでは上記の表にあるような網羅性はありません。また、PyQの場合、それを割と小さな単元で(「クエスト」という名前になっています。)進めていけるので、まとまった時間が取れなくても少しずつやっていくことも可能です。それでも前述のサブスクとの関連性でいえば微妙ですが。例えばGWだけど、COVIDでどこにもいけないで暇だ、なんて時に集中してやってしまうなんて時にはいいと思います。edXは毎週課題が出るようなシステムですので、やろうと思った時にめちゃくちゃ進めちゃおう!なんてことはなかなかできません。

 

Python学習比較

私がこれまでにPythonの学習で使用したものは以下になります。

  • 書籍『Python 1年生 体験してわかる!会話でまなべる!プログラミングのしくみ』
  • edX "Introduction to Computer Science and Programming Using Python"
  • PyQ

実際にやってみた比較ですが、以下のようになりました。「学習レベル・範囲」と、「勉強方法」で比較しています。「学習レベル・範囲」では、その難しさに加え、どれだけのレベルの範囲があるかも考慮しています。また、「勉強方法」の軸は、写経中心なのか、自分でコードを考えるのが中心なのかという軸です。

f:id:KenSuzuki1:20210412235809p:plain

 このようにまとめたところ、学習する順番としては、まず書籍で基本を学んだり、モチベーションを高めてからPyQをはじめ、その途中でedXを同時進行して行くのがいいと思います。ただ、先ほどから記載しているように、PyQはサブスク、edXは基本無料だがテストの期限がある、という特性も考慮すべきかなとは思います。学習範囲が広いからといってだらだらPyQをやっていくのはやはり費用対効果上、お勧めできません。ただ、期限とか無くても自分でタイムマネジメントをしてガシガシやっていけるかたのほうがお勧めです。もし期限が欲しいのであればedXの方がいいでしょう。

 

まとめ

いかがだったでしょうか。いろいろ記載させていただきましたが、このPython関連の Learning Project はこれで終了となります。約2ヶ月のプロジェクトですが、一通り基本は学べたかなと考えます。ですが、少し物足りないのが、成果が実際に見えたり使えるものではないということです。まあほとんどのスキルはその成果や効果がすぐに使えたり見えたりするものではないかもしれませんが、できればあった方が学習のモチベーションの維持に役立つように思います。

 ただ、今回は広く浅く学習し、プログラミングやPythonがどんなもんか、どのように動いているのかを学習することが目的でしたので、その目的は果たしたかと思います。成果のみを求めて学習する目的を失うことはありませんでした。

そして、これを次に活かすためには新しい Learning Project を始めるべきかなと思います。今度は、その目的が「とある成果物」であるようなプロジェクトにしようと思います。是非楽しみにしてください。ありがとうございました。

 

f:id:KenSuzuki1:20210211005354p:plain

 

edXを利用して新しいスキルを習得する (Finance & Management- 001)

またまた新しい Learning Project を始めます。ここ最近新しい Learning Projectを初めてばかりな気もしますが、色々初めてからそれをタイムマネジメントするのもこれから必要なスキルではないかと考え、一度に複数の Learning Project を行うことにしました。 

ここで始めるのは、またedXを用いて学習します。というのも、先日、Introduction to Computer Science and Programming Using Python をやり終えましたので、次に続けて何かを学びたいと考えたからです。いいと思った教育サービスはとことん利用して見ます。

 

勉強する内容

では、何を勉強するかですが、金融関連を学びたいと思います。少しさぼりがちですが、経済学の名著を読む、という Learning Project をやっており、その親和性が高いと思うことと、金融というテーマもあまりきちんと勉強してこなかったなと考えるからです。

edX で Finance で探すときには、Subject より探すと便利です。すぐに Economics & Finance というところが見つかります。また、Business & Management にもありそうです。しかしながら、この二つでソートして見ても、それぞれ396、及び879のコースが見つかります。そこで前回同様 Partner でさらにソートすることにします。そうすると、New York Institute of Finance が最も多いことがわかります。まあ多いということはそれだけいいコースを提供している可能性があると考え、まずはこれをソートします。また、これはかなり個人的なことにはなりますが、Columbia も入れておきます。

その後、楽しそうなのと少し何だろうと思うので分類します。単純に Numbers を利用して一度まとめました。以下がその表で、左側のグレーでハッチングしているのが楽しそう部類です。今回はそれを上からやっていこうかなと考えます。

f:id:KenSuzuki1:20210411211112p:plain

edX: Finance & Management List

これらのコースのほとんどが、self-paced on your time にて開催されており、いつでも初めてもいいものとして設定されています。自分で時間を設定して学習していけそうです。ただ、それにも関わらず Certificate に関しては、かなり高額になっていました。ですので今回は Certificate は取得せずに、面白ければそのまま続けるし、そうでもないなと思ったらすぐ次に切り替えていこうかなと思います。さらに、だいたいのものが 3-4week となっていますが、2-4h/w程度となっていますので、もうちょっとやればどんどん進めていけそうです。一つやったらブログにアップしていけば、この Learning Progect × Blog にも良さそうです。

可能であれば週1程度で一個づつやっていけたらなと考えます。ちょっと忙しくなりそうですが、よろしくお願いいたします。

 

f:id:KenSuzuki1:20210210210105p:plain

 

鉛筆デッサンのスキル上達(001)

またまた新しい Learning Project を始めます。今回はこれまでと趣向が異なります。その名も「鉛筆デッサンのスキル上達」です。

これまでは比較的知識ベースの習得であることが多かったように思います。ですが、今回はそれを芸術に適用しようというものです。これはこのプロジェクトの発端ともなった "Ultralearning" にもあるもので、1ヵ月を使って顔を描くスキルを向上させてみることにするというものでした。

 

現状のレベル

実は絵を描くのはもともと好きなことでもありました。建築系の大学に入学したこともあり、大学での設計製図の最初の課題は、キャンパスのどこでもいいので「階段」を描くというものだったように記憶しています。これを書くと同じ大学出身だ、とわかってしまう方もいらっしゃる方もいるかもしれません。

ですが、ちゃんと絵を描くことを学んだか、といえばそうではありません。まあだいたい描けているからいいかな、なんて考え、先ほどの課題などは、落第しないくらいの成績でなんとかクリアしたことを覚えています。

 

何が必要か

そもそも鉛筆のデッサンにしようと思った理由は、それがもっとも基本であるように思えたからです。また、準備も簡単で、鉛筆と紙があれば最低限できます。準備に関しては早速、新宿の「世界堂」に向かい、必要だと思われるものを購入しました。また、ちょうどそこに基本を学ぶための図書もあったのでついでに購入しました。合わせて3,000円程度です。

f:id:KenSuzuki1:20210410181737j:plain

デッサンをするにあたって購入したもの

この図書の中身を見ながら必要なものを要したのですが、まあ鉛筆は必要そうです。ちょうど表紙に載っているように、「ステッドラー マルス ルモグラフ」をオススメしていたので、まあ定番でもありますし、その6本セットを購入しました。なんかあまりにも濃い鉛筆が多かったのが気になりましたが。

紙ですが、スケッチブックを使用することにしました。昔よく使用していたマルマンのよく見るやつがありましたので、これを今回は使っていきます。クロッキーのものですと、何回も消したりすると破れたりする危険性がありますので、こちらの少し厚い紙のものにしました。

他に練り消しとカッターを購入し、準備完了です。また、ちょっとカッターで鉛筆を削るのが不安なので家にあった鉛筆削りを引っ張り出してきました。

 

何を描くか

最初は "Ultralearning" と同様に自画像をやろうかなと思いましたが、購入した書籍を読んで見たところ、静物から初めて基礎を習得していました。単純な形のものから初め、徐々に複雑なものにしています。最終的にこの図書では石膏像までを扱っています。ですので自分もある程度これにのっとり、最初は静物から初め、最終的に自画像を描きます。本当の最後の目標は自分のアイコンをその自画像にすることです。

 

どのように上達させるか

静物までであればこの書籍に載っていることを勉強すれば良さそうです。ですが自画像へとなると自分で良し悪しを見極めなければなりません。この Learning Project では、実際にテストをして、すぐにフィーとバックを得ることで学びを得ようとしています。ですので、自画像になったら、

  1. まず描く
  2. 実際のものと描いたものの両方の写真をそれぞれ撮る
  3. 比較してフィードバックを獲る

という順序でやっていきたいと思います。

 

それでは新しい Learning Project の始まりです。これまでとかなり趣向の異なるものになりましたが、チャレンジしたいものでしたので頑張りたいと思います。これはこまめに続きを記載できたらと思います。よろしくお願いします。

f:id:KenSuzuki1:20210410184554p:plain

 

ファイナンシャル・プランナー(FP)資格の取得 (001)

こんにちは。新しい Learning Project を始めます。今回は資格の取得を通してスキルを身につけようと思います。と言うのも、やはり何かしらの成果があることでモチベーションの維持や成果の結果がわかりやすく、この Learning Project にも適合しやすいと思うからです。

 

なんの資格を取得するか

ただ、日本で見ただけでも資格にはかなりの数があります。世の中には資格マニアなる人もいて、なんでもかんでもとっているような人もいるそうです。幅広い知識を得ると言う面ではいいと思いますが、そこまで労力をかける時間も無いので絞るしかありません。

そこで今回はファイナンシャルプランナー(FP)という資格の取得を目指します。理由ですが、以下の2つがあります。1つ目は感情的な側面です。まあファイナンス系の資格でちょっと面白いかな、と思ったからです。やはりモチベーションの維持や理解どにも関わってきそうではあります。2つ目は実務的な面です。今まではそんなにお金のことを気にせずいきてこれましたが、これからは人生において色々なイベントごとが発生し、その度に状況が変化しそうです。その度にお金の問題は関わってきそうなので、広く薄い知識でもあったほうがいいかなと思ったからです。

さらには実際問題、本当に取れるかという問題があります。自分の予定上、あまり未来になってしまうと受験ができないかもしれません。ファイナンシャルプランナーについて少し調べたところ、次の試験は5月にあるようでしたのでそこの問題がありませんでした。

 

何級を取得するか

次に、何級を取得するかという問題になります。実際には1〜3級があり、それぞれまあ難しさが異なるようです。本当は2級を受けようと思っていました。ですが、さらに調べたら2級からは受験資格が必要で、2級の受験資格は

  • AFP認定研修の受講修了者
  • 3級FP技能検定合格者
  • FP実務経験2年以上
  • とのことです。実務経験はありませんし、研修を受けたのではこの Learning Project の意味があまり無いので、これは地道に3級から合格していくべきかなと思いました。正直今までの Learning Project に比べたら少し簡単かな、と思いましたが、まあそんなとこでもいいでしょう。

 

そもそもFP資格って何か

実はこれをあまり理解せずに資格名でスタートしようと考えていました。一応国家資格であり、ファイナンシャル・プランニング技能検定として1〜3級があり、日本FP協会認定資格としてAFP資格とCFP資格という上位資格があるようです。また、試験は「金融財政事情研究会(金財)」と「日本ファイナンシャル・プランナーズ協会」の2団体が実施しており、どちらで受けるかを決める必要があります。

この2つについてですが、午後に行われる実技試験に差があるようです。金財では、個人資産相談業務もしくは保険顧客資産相談業務から出題されるのに対し、日本FP協会では資産設計提案業務から出るとのことです。これもネットからの情報ですが、金財は少し難しいが範囲が狭い、日本FP協会は少し簡単だが範囲が広い、とのことでした。ただ、それを考えた時に、今回この資格を取得しようと思った動機は、幅広い知識を得たい!の方ですので、今回は日本FP協会にて受けようと思います。

 

どのように勉強するか

もちろん独学で、この Learning Project に基づいて資格取得に向けて学習します。ということですが、まあ流石に今回は書籍に頼るしかなさそうです。早速本屋にいくことにしました。本屋に行くとそこそこ対策本が並んでおり、人気が伺えます。今回は以下2冊を購入しました。

 

みんなが欲しかった! FPの教科書 3級 2020-2021年 (みんなが欲しかった! シリーズ)
 
みんなが欲しかった! FPの問題集 3級 2020-2021年 (みんなが欲しかった! シリーズ)
 

 これに決めた理由ですが、売り上げNo. 1とあったからです。まあどれもそんなに変わりは無いだろうと思って購入しました。

ちなみに参考までに取得までの勉強時間ですが、かのユーキャン曰く、

ファイナンシャルプランナー(FP)3級の試験に合格するために必要な勉強時間は、80〜150時間程度が目安になります。1日2時間勉強するのであれば、2〜3カ月程度の期間が必要になる計算です。

とのことです。実際の試験日ですが、今年は5月23日とのことですので、あと約1カ月半となります。Learning Project で勉強することの効率性を過大評価すると、1日1時間で約45時間は確保できそうなので、これで行こうと思います。

ところで、ここで考えることは、普通であるとまずは濃いピンクの方の「教科書」なる本からやってしまいがちです。ですが、やはり今回は、「テストを早めに受け、それを元にフィードバックを受け取る」という手法を取りたいと思いますので薄いピンクの方の「問題集」なる本から手をつけようと思っています。

 

とりあえずこれでまた新たな Learning Project をスタートさせました。今までより難しくはないかもしれないとたかをくくっていますが、まあそれでも新しい知識を得ることになります。知的好奇心を高く保ちながら勉強に励みたいと思います。期をみて中間報告などできればと思います。

f:id:KenSuzuki1:20210409065939p:plain

 

edXを利用して新しいスキルを習得する (Programming- 009)

引き続き、edXでのIntroduction to Computer Science and Programming Using Pythonを記載します。後半戦の Unit 4 から最後の Final Examまでになります。また、最後に感想等を記載したいと思います。

今回も前回同様、目次から記載します。

 

 

Unit 4: Good Programming Practices

7. Testing and Debugging / 8. Exceptions and Assertions

 コードを書いていてもどうしてもうまくいかない時があります。そんな時に役立つコードの修正方法について説明していきます。例えばPythonがエラーの場所や種類を教えてくれるのを解読したり、あちこちに"print"を挟んでおいて確認するような手法です。また、"try"や"except"、"raise"を用いて事前にエラーを回避するような方法も解説してくれます。最終的には、また言葉を使ったゲームを作成します。正直完全な日本人の私には全く馴染みがなく、これも難しかったですが、一つ一つ問題を解いていくと一つのゲームが完成するようになっていたり、お助けコードが書かれていたりして手助けしてくれます。(他のSetのものも同様ですが、words.txtファイルが必要です。)

# Word Game

import random

VOWELS = 'aeiou'
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'
HAND_SIZE = 7
SCRABBLE_LETTER_VALUES = { 'a': 1, 'b': 3, 'c': 3, 'd': 2, 'e': 1, 'f': 4, 'g': 2, 'h': 4, 'i': 1, 'j': 8, 'k': 5, 'l': 1, 'm': 3, 'n': 1, 'o': 1, 'p': 3, 'q': 10, 'r': 1, 's': 1, 't': 1, 'u': 1, 'v': 4, 'w': 4, 'x': 8, 'y': 4, 'z': 10}

# -----------------------------------
# Helper code

WORDLIST_FILENAME = "words.txt"
def loadWords():
    """
    Returns a list of valid words. Words are strings of lowercase letters.
    Depending on the size of the word list, this function may take a while to finish.
    """
    print("Loading word list from file...")
    # inFile: file
    inFile = open(WORDLIST_FILENAME, "r")
    # wordList: list of strings
    wordList = [ ]
    for line in inFile:
        wordList.append(line.strip().lower())
    print("  ", len(wordList), "words loaded.")
    return wordList


def getFrequencyDict(sequence):
    """
    Returns a dictionary where the keys are elements of the sequence and the values are integer counts, for the number of times that an element is repeated in the sequence.
    sequence: string or list
    return: dictionary
    """
    # freqs: dictionary (element_type -> int)
    freq = {}
    for x in sequence:
        freq[x] = freq.get(x, 0) + 1
    return freq

# (end of helper code)
# -----------------------------------

#
# Problem #1: Scoring a word
#


def getWordScore(word, n):
    """
    Returns the score for a word. Assumes the word is a valid word.
    The score for a word is the sum of the points for letters in the word, multiplied by the length of the word, PLUS 50 points if all n letters are used on the first turn.
    Letters are scored as in Scrabble; A is worth 1, B is worth 3, C is worth 3, D is worth 2, E is worth 1, and so on (see SCRABBLE_LETTER_VALUES)
    word: string (lowercase letters)
    n: integer (HAND_SIZE; i.e., hand size required for additional points)
    returns: int >= 0
    """
    # TO DO ... <-- Remove this comment when you code this function
    score = 0
    for letter in word:
        score += SCRABBLE_LETTER_VALUES[letter]
    score *= len(word)
    if len(word) == n:
        score += 50
    return score


def displayHand(hand):
    """
    Displays the letters currently in the hand.
    For example:
    >>> displayHand({'a':1, 'x':2, 'l':3, 'e':1})
    Should print out something like:
       a x x l l l e
    The order of the letters is unimportant.
    hand: dictionary (string -> int)
    """
    for letter in hand.keys():
        for j in range(hand[letter]):
             print(letter, end = " ")       # print all on the same line
    print()                                       # print an empty line



def dealHand(n):
    """
    Returns a random hand containing n lowercase letters.
    At least n/3 the letters in the hand should be VOWELS.
    Hands are represented as dictionaries. The keys are letters and the values are the number of times the particular letter is repeated in that hand.
    n: int >= 0
    returns: dictionary (string -> int)
    """
    hand={}
    numVowels = n // 3

    for i in range(numVowels):
        x = VOWELS[random.randrange(0,len(VOWELS))]
        hand[x] = hand.get(x, 0) + 1
    for i in range(numVowels, n):
        x = CONSONANTS[random.randrange(0, len(CONSONANTS))]
        hand[x] = hand.get(x, 0) + 1

    return hand


#
# Problem #2: Update a hand by removing letters
#


def updateHand(hand, word):
    """
    Assumes that 'hand' has all the letters in word.
    In other words, this assumes that however many times a letter appears in 'word', 'hand' has at least as many of that letter in it. 
    Updates the hand: uses up the letters in the given word and returns the new hand, without those letters in it.
    Has no side effects: does not modify hand.
    word: string
    hand: dictionary (string -> int)
    returns: dictionary (string -> int)
    """
    # TO DO ... <-- Remove this comment when you code this function
    output = hand.copy()
    for letter in word:
        if letter in output.keys():
            output[letter] -= 1
    return output

#
# Problem #3: Test word validity
#


def isValidWord(word, hand, wordList):
    """
    Returns True if word is in the wordList and is entirely composed of letters in the hand. Otherwise, returns False.
    Does not mutate hand or wordList.
    word: string
    hand: dictionary (string -> int)
    wordList: list of lowercase strings
    """
    # TO DO ... <-- Remove this comment when you code this function
    output = hand.copy()
    word_check = False
    if word in wordList:
        word_check = True

    letter_check = set(list(word)) <= set(output.keys())

    for letter in word:
        if letter in output.keys():
            output[letter] -= 1

    value_check = all(i >= 0 for i in output.values())

    if word_check == True and letter_check == True and value_check == True:
        return True
    else:
        return False

#
# Problem #4: Hand length
#


def calculateHandlen(hand):
    """
     Returns the length (number of letters) in the current hand.
     hand: dictionary (string-> int)
    returns: integer
    """
    # TO DO... <-- Remove this comment when you code this function
    sumvalue = 0
    for value in hand.values():
        sumvalue += value
    return sumvalue

#
# Problem #5: Playing a Hand
#


def playHand(hand, wordList, n):
    """
    Allows the user to play the given hand, as follows:
    * The hand is displayed.
    * The user may input a word or a single period (the string ".") to indicate they're done playing
    * Invalid words are rejected, and a message is displayed asking the user to choose another word until they enter a valid word or "."
    * When a valid word is entered, it uses up letters from the hand.
    * After every valid word: the score for that word is displayed, the remaining letters in the hand are displayed, and the user is asked to input another word.
    * The sum of the word scores is displayed when the hand finishes.
    * The hand finishes when there are no more unused letters or the user inputs a "."

      hand: dictionary (string -> int)
      wordList: list of lowercase strings
      n: integer (HAND_SIZE; i.e., hand size required for additional points)
      """
    # BEGIN PSEUDOCODE <-- Remove this comment when you code this function; do your coding within the pseudocode (leaving those comments in-place!)
    # Keep track of the total score
    score = 0
    # As long as there are still letters left in the hand:
    while calculateHandlen(hand) > 0:
        # Display the hand
        print("Current Hand:", displayHand(hand))
        # Ask user for input
        guess = str(input('Enter word, or a "." to indicate that you are finished: '))
        # If the input is a single period:
        if guess == ".":
            # End the game (break out of the loop)
            break
        # Otherwise (the input is not a single period):
        else:
            # If the word is not valid:
            if isValidWord(guess, hand, wordList) == False:
                # Reject invalid word (print a message followed by a blank line)
                print("Invalid word, please try again.", "\n")
            # Otherwise (the word is valid):
            else:
                # Tell the user how many points the word earned, and the updated total score, in one line followed by a blank line
                score += getWordScore(guess, n)
                # Update the hand
                 hand = updateHand(hand, guess)
    # Game is over (user entered a '.' or ran out of letters), so tell user the total score        if guess == ".":
        print("Goodbye! Total score:", score, "points.")
    else:
        print("Run out of letters. Total score:", score, "points.")

#
# Problem #7: You and your Computer
# Computer chooses a word
#

def compChooseWord(hand, wordList, n):
    """
    Given a hand and a wordList, find the word that gives the maximum value score, and return it.
    This word should be calculated by considering all the words in the wordList.
    If no words in the wordList can be made from the hand, return None.
    hand: dictionary (string -> int)
    wordList: list (string)
    n: integer (HAND_SIZE; i.e., hand size required for additional points)
    returns: string or None
    """
    # Create a new variable to store the maximum score seen so far (initially 0)
    bestScore = 0
    # Create a new variable to store the best word seen so far (initially None)
    bestWord = None
    # For each word in the wordList
    for word in wordList:
        # If you can construct the word from your hand
        if isValidWord(word, hand, wordList):
            # find out how much making that word is worth
            score = getWordScore(word, n)
            # If the score for that word is higher than your best score
            if (score > bestScore):
                # update your best score, and best word accordingly
                bestScore = score
                bestWord = word
    # return the best word you found
    return bestWord

#
# Computer plays a hand
#


def compPlayHand(hand, wordList, n):
    """
    Allows the computer to play the given hand, following the same procedure as playHand, except instead of the user choosing a word, the computer chooses it.
    1) The hand is displayed. 
  2) The computer chooses a word.
    3) After every valid word: the word and the score for that word is displayed, the remaining letters in the hand are displayed, and the computer chooses another word.
    4)  The sum of the word scores is displayed when the hand finishes.
    5)  The hand finishes when the computer has exhausted its possible choices (i.e. compChooseWord returns None).
     hand: dictionary (string -> int)
    wordList: list (string)
    n: integer (HAND_SIZE; i.e., hand size required for additional points)
    """
    # Keep track of the total score
    totalScore = 0
    # As long as there are still letters left in the hand:
    while (calculateHandlen(hand) > 0) :
        # Display the hand
        print("Current Hand: ", end=" ")
        displayHand(hand)
        # computer's word
        word = compChooseWord(hand, wordList, n)
        # If the input is a single period:
        if word == None:
            # End the game (break out of the loop)
            break
        # Otherwise (the input is not a single period):
        else :
            # If the word is not valid:
            if (not isValidWord(word, hand, wordList)) :
                print("This is a terrible error! I need to check my own code!")
                break
            # Otherwise (the word is valid):
            else :
                # Tell the user how many points the word earned, and the updated total score
                score = getWordScore(word, n)
                totalScore += score
                print('"' + word + "earned" + str(score) + "points. Total: " + str(totalScore) + "points")
                # Update hand and show the updated hand to the user
                hand = updateHand(hand, word)
                print()
    # Game is over (user entered a '.' or ran out of letters), so tell user the total score
    print("Total score: " + str(totalScore) + " points.")


def playGame(wordList):
    """
    Allow the user to play an arbitrary number of hands.
     1) Asks the user to input 'n' or 'r' or 'e'.
        * If the user inputs 'e', immediately exit the game.
        * If the user inputs anything that's not 'n', 'r', or 'e', keep asking them again.
     2) Asks the user to input a 'u' or a 'c'.
        * If the user inputs anything that's not 'c' or 'u', keep asking them again.
     3) Switch functionality based on the above choices:
        * If the user inputted 'n', play a new (random) hand.
        * Else, if the user inputted 'r', play the last hand again.
          But if no hand was played, output "You have not played a hand yet. Please play a new hand first!"
        * If the user inputted 'u', let the user play the game with the selected hand, using playHand.
        * If the user inputted 'c', let the computer play the game with the selected hand, using compPlayHand.
     4) After the computer or user has played the hand, repeat from step 1

    wordList: list (string)
    """
    # TO DO ... <-- Remove this comment when you code this function
    while True:
        user_input = str(input("Enter n to deal a new hand, r to replay the last hand, or e to end game: "))
        if user_input == "e":
            break
        elif user_input == "n":
            while True:
                play_mode = str(input("Enter u to have yourself play, c to have the computer play: "))
                if play_mode == "u":
                    hand = dealHand(HAND_SIZE)
                    playHand(hand, wordList, HAND_SIZE)
                    break
                elif play_mode == "c":
                    hand = dealHand(HAND_SIZE)
                    compPlayHand(hand, wordList, HAND_SIZE)
                    break
                else:
                    print("Invalid command.")
        elif user_input == "r":
            try:
                hand
                play_mode = str(input("Enter u to have yourself play, c to have the computer play: "))
                if play_mode == "u":
                    playHand(hand, wordList, HAND_SIZE)
                elif play_mode == "c":
                    compPlayHand(hand, wordList, HAND_SIZE)
                else:
                    print("Invalid command.")
            except:
                print("You have not played a hand yet. Please play a new hand first!")
        else:
            print("Invalid command.")   


#
# Build data structures used for entire session and play game
#
if __name__ == '__main__':
    wordList = loadWords()
    playGame(wordList)

 

Unit 5: Object Oriented Programming

9. Classes and Inheritance / 10. An Extended Example

 現代のプログラミングの設計方法論として、最もメジャーなオブジェクト指向を学びます。その説明も最初に少しするくらいで、あとは実際にやって見てそれを見せると言う方法を取っているのが面白いところです。実際には、「動物」のクラスを作成し、「猫」といった階層を定義したり、さらには「人間」、「MITの人間」、「学生」、「成績」と定義していきます。そこからどのように値を入力し、そして抽出するのかを学びます。最終的にはオブジェクト指向を用いて暗号を解くプログラムを作成します。

 

import string

### DO NOT MODIFY THIS FUNCTION ###
def load_words(file_name):
    '''
    file_name (string): the name of the file containing
    the list of words to load
    Returns: a list of valid words. Words are strings of lowercase letters.
    Depending on the size of the word list, this function may take a while to finish.
    '''
    print("Loading word list from file...")
    # inFile: file
    in_file = open(file_name, "r")
    # line: string
    line = in_file.readline()
    # word_list: list of strings
    word_list = line.split()
    print(" ", len(word_list), "words loaded.")
    in_file.close()
    return word_list


### DO NOT MODIFY THIS FUNCTION ###
def is_word(word_list, word):
    '''
    Determines if word is a valid word, ignoring capitalization and punctuation

    word_list (list): list of words in the dictionary.
    word (string): a possible word.
    Returns: True if word is in word_list, False otherwise

    Example:
    >>> is_word(word_list, 'bat') returns
    True
    >>> is_word(word_list, 'asdf') returns
    False
    '''
    word = word.lower()
    word = word.strip(" !@#$%^&*()-_+={}[]|\:;'<>?,./\"")
    return word in word_list


### DO NOT MODIFY THIS FUNCTION ###
def get_story_string():
    """
    Returns: a joke in encrypted text.
    """
    f = open("story.txt", "r")
    story = str(f.read())
    f.close()
    return story

WORDLIST_FILENAME = "words.txt"



class Message(object):
    ### DO NOT MODIFY THIS METHOD ###
    def __init__(self, text):
    '''
    Initializes a Message object
    text (string): the message's text

    a Message object has two attributes:
        self.message_text (string, determined by input text)
        self.valid_words (list, determined using helper function load_words
    '''
    self.message_text = text
    self.valid_words = load_words(WORDLIST_FILENAME)


    ### DO NOT MODIFY THIS METHOD ###
    def get_message_text(self):
        '''
        Used to safely access self.message_text outside of the class
        Returns: self.message_text
        '''
        return self.message_text

    ### DO NOT MODIFY THIS METHOD ###
    def get_valid_words(self):
        '''
        Used to safely access a copy of self.valid_words outside of the class
        Returns: a COPY of self.valid_words
        '''
        return self.valid_words[:]

    def build_shift_dict(self, shift):
        '''
        Creates a dictionary that can be used to apply a cipher to a letter.
        The dictionary maps every uppercase and lowercase letter to a character shifted down the alphabet by the input shift. The dictionary should have 52 keys of all the uppercase letters and all the lowercase letters only.
        shift (integer): the amount by which to shift every letter of the
        alphabet. 0 <= shift < 26

        Returns: a dictionary mapping a letter (string) to
        another letter (string).
        '''
        lower_keys = list(string.ascii_lowercase)
        lower_values = list(string.ascii_lowercase)
        lower_shift_values = lower_values[shift:] + lower_values[:shift]

        upper_keys = list(string.ascii_uppercase)
        upper_values = list(string.ascii_uppercase)
        upper_shift_values = upper_values[shift:] + upper_values[:shift]

        full_keys = lower_keys + upper_keys
        full_values = lower_shift_values + upper_shift_values

        self.shift_dict = dict(zip(full_keys, full_values))
        return self.shift_dict


    def apply_shift(self, shift):
        '''
        Applies the Caesar Cipher to self.message_text with the input shift.
        Creates a new string that is self.message_text shifted down the alphabet by some number of characters determined by the input shift
        shift (integer): the shift with which to encrypt the message.
        0 <= shift < 26

        Returns: the message text (string) in which every character is shifted down the alphabet by the input shift
        '''
        new_msg = [ ]
        for i in self.message_text:
            if i not in self.build_shift_dict(shift).keys():
                new_msg.append(i)
                continue
             else:
                 new_msg.append(self.build_shift_dict(shift)[i])
        return "".join(new_msg)



class PlaintextMessage(Message):
    def __init__(self, text, shift):
        '''
        Initializes a PlaintextMessage object
        text (string): the message's text
        shift (integer): the shift associated with this message

        A PlaintextMessage object inherits from Message and has five attributes:
            self.message_text (string, determined by input text)
            self.valid_words (list, determined using helper function load_words)
            self.shift (integer, determined by input shift)
            self.encrypting_dict (dictionary, built using shift)
            self.message_text_encrypted (string, created using shift)

        Hint: consider using the parent class constructor so less code is repeated
        '''
        self.shift = shift
        self.message_text = text
        self.valid_words = load_words(WORDLIST_FILENAME)
        self.encrypting_dict = super(PlaintextMessage, self).build_shift_dict(shift)
        self.message_text_encrypted = super(PlaintextMessage, self).apply_shift(shift)


    def get_shift(self):
        '''
        Used to safely access self.shift outside of the class
        Returns: self.shift
        '''
        return self.shift


    def get_encrypting_dict(self):
        '''
        Used to safely access a copy self.encrypting_dict outside of the class
        Returns: a COPY of self.encrypting_dict
        '''
        encrypting_dict_copy = self.encrypting_dict.copy()
        return encrypting_dict_copy


    def get_message_text_encrypted(self):
        '''
        Used to safely access self.message_text_encrypted outside of the class
        Returns: self.message_text_encrypted
        '''
        return self.message_text_encrypted


    def change_shift(self, shift):
        '''
        Changes self.shift of the PlaintextMessage and updates other
        attributes determined by shift (ie. self.encrypting_dict and message_text_encrypted).
        shift (integer): the new shift that should be associated with this message.
        0 <= shift < 26

        Returns: nothing
        '''
        self.shift = shift
        self.encrypting_dict = super(PlaintextMessage, self).build_shift_dict(shift)
        self.message_text_encrypted = super(PlaintextMessage, self).apply_shift(shift)



class CiphertextMessage(Message):
    def __init__(self, text):
        '''
        Initializes a CiphertextMessage object
        text (string): the message's text

        a CiphertextMessage object has two attributes:
            self.message_text (string, determined by input text)
            self.valid_words (list, determined using helper function load_words)
        '''
        self.message_text = text
        self.valid_words = load_words(WORDLIST_FILENAME)


    def decrypt_message(self):
        '''
        Decrypt self.message_text by trying every possible shift value and find the "best" one. We will define "best" as the shift that creates the maximum number of real words when we use apply_shift(shift) on the message text. If s is the original shift value used to encrypt the message, then we would expect 26 - s to be the best shift value for decrypting it.

    Note: if multiple shifts are equally good such that they all create the maximum number of you may choose any of those shifts (and their corresponding decrypted messages) to return

    Returns: a tuple of the best shift value used to decrypt the message and the decrypted message text using that shift value
        '''
        word_counter = 0
        max_count = 0
        for i in range(26):
            for j in list(super(CiphertextMessage, self).apply_shift(i).split(' ')):
                if is_word(self.valid_words, j):
                    word_counter += 1
                if word_counter > max_count:
                    max_count = word_counter
                    shift_value = i
                    decrypted_msg = super(CiphertextMessage, self).apply_shift(i)

        return (shift_value, decrypted_msg)


#Example test case (PlaintextMessage)
plaintext = PlaintextMessage('hello', 2)
print('Expected Output: jgnnq')
print('Actual Output:', plaintext.get_message_text_encrypted())

#Example test case (CiphertextMessage)
ciphertext = CiphertextMessage('jgnnq')
print('Expected Output:', (24, 'hello'))
print('Actual Output:', ciphertext.decrypt_message())

 

Unit 6: Algorithmic Complexity

11. Computational Complexity / 12. Searching and Sorting Algorithms

これまでプログラムを実際に書くことでプログラミングを学んできましたが、ここでそのプログラムがどのくらいの大きさのものを扱い、それがどのように増えていくのかを評価することでプログラムの効率性を考えます。この単元では、最後のテストが選択式であり、プログラムを書きません。ですので、その講義で扱ったソートの手段によるプログラムの上昇具合を見ることでどのようなことを言っているのかを紹介します。 

Bogo-Sort

import random
def bogo_sort(L):
    while not is_sorted(L):
        random.shuffule(L)

 

Bubble-Sort

def bubble_sort(L):
    swap = False
    while not swap:
        swap = True
        for j in range(1, len(L)):
            if L[j - 1] > L[j]:
                swap = False
                temp = L[j]
                L[j] = L[j -1]
                L[j -1] = L[j]

 

Selection-Sort

def selection_sort(L):
    suffixSt = 0
    while suffixSt != len(L):
        for i in range(suffixSt, len(L)):
            if L[i] < L[suffixSt]:
                L[suffixSt], L[i] = L[i], L[suffixSt]
        suffixSt += 1

 

Merge-Sort

def merge_sort(left, right):
    result = [ ]
    i, j = 0, 0
    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    while (i < len(left)):
        result.append(left[i])
        i += 1
    while (j < len(right)):
        result.append(right[j])
        j += 1
    return result

 

Unit 7: Plotting

13. Plotting

 この単元には一つの項目しかなく、これまで学んだプログラムの書き方を使用して、数字をプロットし、可視化する方法を学びます。さらにはそれを効果的に見せる方法を説明していきます。実際には、リタイアしてからの貯金の伸び方をシミュレーションするようなグラフを描きます。

import pylab as plt

def retire(monthly, rate, terms):
    savings = [0]
    base = [0]
    mRate = rate / 12
    for i in range(terms):
       base += [i]
       savings += [savings[-1] * (1 + mRate) + monthly]
    return base, savings


def displayRetireWMonthlies(monthlies, rate, terms):
    plt.figure("retireMonth")
    plt.clf()
    for monthly in monthlies:
       xvals, yvals = retire(monthly, rate, terms)
       plt.plot(xvals, yvals, label = "reitre: " + str(monthly))
       plt.legend(loc = "upper left")


def displayRetireWRates(month, rates, terms):
    plt.figure("retireRate")
    plt.clf()
    for rate in rates:
       xvals, yvals = retire(month, rate, terms)
       plt.plot(xvals, yvals, label = "retire: " + str(month) + ":" + str(int(rate * 100)))
       plt.legend(loc = "upper left")

def displayRetireWMonthsAndRates(monthlies, rates, terms):
    plt.figure("retireBoth")
    plt.clf()
    plt.xlim(30*12, 40*12)
    monthLabels = ["r", "b", "g", "k"]
    rateLabels = ["-", "o", "--"]
    for i in range(len(monthlies)):
       monthly = monthlies[i]
       monthLabel = monthLabels[i % len(monthLabels)]
          for j in range(len(rates)):
          rate = rates[j]
          rateLabel = rateLabels[j % len(rateLabels)]
          xvals, yvals = retire(monthly, rate, terms)
          plt.plot(xvals, yvals, monthLabel + rateLabel, label = "retire: " + str(monthly) + ":" + str(int(rate * 100)))
          plt.legend(loc = "upper left")

 

displayRetireWMonthsAndRates([500,700,900,1100],[.03,.05,.07], 40*12)

f:id:KenSuzuki1:20210408131104p:plain

displayRetireWMonthsAndRates

 

Final Exam

とうとう最終試験です。Midterm Exam と同様の手法で行われ、一定の期間が設定されており、その期間の内であればいつでも受験可能です。問題はランダムで出ますが、その難しさは一定ですよ、とやはり書いてあります。そしてやり始めたら8時間通しで全て回答するまで行わなければなりません。実際にプログラムを書くのは計5題出題され、今までやった復習的な問題もあったり、授業でやったことの続き的な問題もあります。プログラムのスキルだけでなく、論理的に考える力も必要でした。よくよく読むとインターネット等にアップしないでね!って書いてありましたので、ここで記載するのは控えます。

 

 

edX: Introduction to をやり終えた感想

2ヶ月強に及ぶこのコースでしたが、かなり手応えのあるものでした。本当に最初は基本から始まりますが、かなりの急スピードで進んでいきます。以前にも書きましたが、正直なところ他のサービスと併用して学ばないとついていけないと感じました。ただ、もともと他の言語ができるなどの知識がある方についてはいいのかもしれません。

しかしながら、まあまあプログラミングやPythonとはなんたるや、と言うところは理解できてきたように思います。実際、これを使って業務をしたい!といった本格的に学ぶ人にとってはまだまだ学ぶところもあるのかもしれませんが、とりあえず自分はそうではないので、ここでの目標は果たしたかなと思います。最初は何にも書けなかったことを考えるとかなりの進歩ではないかと自負しています。

それぞれの講義ビデオはよくできており、一つ一つ理解しながら進めます。また、テストがあるために、全てが受け身ではなく、自分で考えることが強制的にできるところがいいところです。明らかにそんなもん習ってない!と思うことがテストには出ますが、それを自分で調べて正解にたどり着くことができることが必要なスキルでないかと思います。実際、インターネットを使用すればあらゆる情報が手に入りました。

 

これで「図書『Python 1年生』」と「edX "Introduction to Computer Science and Programming Using Python」によってPythonを学びました。一長一短ありますが、併用が正しいように思います。また、現状「PyQ」も続けておりますので、このサービスをある程度まで学習し終わったな、と感じたらこれら3つの学び方について比較できればと思います。

 

また、さらに今後の予定ですが、せっかくプログラミングを学びましたので、アプリなどを作成できればと考えています。これを新しい Learning Project として立ち上げ、実際に作りながら学んでいければと思います。前回同様、プログラムコードと合わせるとかなりの長文となって申し訳ありません。ありがとうございました。

 

f:id:KenSuzuki1:20210408133944p:plain

Certificate

f:id:KenSuzuki1:20210211005354p:plain

 

edXを利用して新しいスキルを習得する (Programming- 008)

先日、edXで学習した2つ目のコースである、"Introduction to Computer Science and Programming Using Python" を最後までやり遂げました。"How to Write an Essay" よりかなり分量も難しさもありましたが、ひとまず Programming や Python がどんなものなのかを学ぶことができて満足です。また、Certificate も得ることができました。そこで、これからの2回は、このコースの内容と感想を記載していきたいと思います。

 

今回は、最初の Unit 1 から Midterm Exam までを記載します。だいたい週に1回新しい Unit に入り、その最後にテストがあります。講義はVideoとそれに付随するミニテストからなり、1個の Unit には2つの項目があります。まずはその目次です。

 

 

それでは一つづつみていきましょう。

 

Unit 1: Python Basics

  1. Introduction to Python / 2. Core Elements of Programs

まずはじめに、コンピュータとは何か、プログラムとは何か、といった基本的な知識から、用語の解説まで行っていきます。ここまでは「ふんふん、そーかー」などとしていて大丈夫です。そこから、 "if" や "else" 、"print" や "input" 等の使い方といった、初歩的なところを解説していきます。さらにこの Unit の終盤では、"while" や "for" を用いた繰り返しの方法を学びます。最終的には、ランダムな文字列からアルファベット順になっている部分の中でもっとも長いものを抽出するプログラムを書くところまで行います。

"""
アルファベット順に文字が並んだsの最も長い部分文字列を表示するプログラムを書いてください。
例えば、s = 'azcbobobegghakl' の場合、プログラムは次のように表示します。
Longest substring in alphabetical order is: beggh
"""

s = 'azcbobobegghakl'
count = 0
maxcount = 0
result = 0

for char in range(len(s) -1):
    if (s[char] <= s[char + 1]):
        count += 1
        if count > maxcount:
            maxcount = count
            result = char + 1
    else:
        count = 0
startposition = result - maxcount
print("Longest substring in alphabetical order is:" ,s[startposition:result + 1])

 

Longest substring in alphabetical order is: beggh

 

Unit 2: Simple Programs

  3. Simple Algorithms / 4. Functions

 このUnitでは、"while" や "for" の復習から始まり、新しいこととしてはまず "bisection search" を学習します。これがなかなか理解が難しく、最初の難関でした。ここら辺から正しく理解していないとミニテストですら普通に間違えるようになります。また、ここから頻繁に出てくる Function の使い方を学習します。"Tower of Hanoi" やおなじみの "Fibonacci" 、そして "Palindrome" (回文)を例にしながら、特に "iteration" と "recursion" の違いについて解説してくれます。最終的には、負債があると仮定した時に、いくらづつ返済すれば12ヶ月で返却できるかを返してくれるプログラムをbisection search を用いて書きます。下の表が実際に出てきた例です。

Month Balance Minimum Payment Unpaid Balance Interest
0 5000.00 100 (= 5000 * 0.02) 4900 (= 5000 - 100) 73.50 (= 0.18/12.0 * 4900)
1 4973.50 (= 4900 + 73.50) 99.47 (= 4973.50 * 0.02) 4874.03 (= 4973.50 - 99.47) 73.11 (= 0.18/12.0 * 4874.03)
2 4947.14 (= 4874.03 + 73.11) 98.94 (= 4947.14 * 0.02) 4848.20 (= 4947.14 - 98.94) 72.72 (= 0.18/12.0 * 4848.20)

 

"""
balance: クレジットカードの未決済残高
annualInterestRate: 10進数で表した年利率
**Monthly interest rate = (Annual interest rate) / 12.0
**Monthly payment lower bound = Balance / 12
**Monthly payment upper bound = (Balance * (1 + Monthly interest rate)12) / 12.0
これらの範囲とbisection searchを使って、セントに対する最小の月々の支払い額を求めるプログラムを書いてください。
"""

balance = 320000   # random
annualInterestRate = 0.2   # random

init_balance = balance
monthlyInterestRate = annualInterestRate / 12
lower = init_balance / 12
upper = (init_balance * (1 + monthlyInterestRate)**12 / 12.0
epsilon = 0.03

while abs(balance) > epsilon:
    monthlyPaymentRate = (upper + lower) / 2
    balance = init_balance
    for i in range(12):
        balance = balance - monthlyPaymentRate + ( (balance - monthlyPaymentRate) * monthlyInterestRate)
        if balance > epsilon:
            lower = monthlyPaymentRate
        elif balance < -epsilon:
            upper = monthlyPaymentRate
        else:
            break

print("Lowest Payment:", round(monthlyPaymentRate, 2))

 

Lowest Payment: 29157.09

 

Unit 3: Structured Types

  5. Tuples and Lists / 6. Dictionaries

 ここでは、"Tuple" や "List"、そして"Dictionary"を学習します。それぞれの特徴などから始まり、"List" では、"append" や "remove", "pop" を用いることでその中身を変化させることができることを学びます。"Dictionary" の部分では、曲の中で同じ単語が何回出てくるかを抽出するプログラムを通じてその用法について説明されます。最終的には、"Hangman" という単語あてゲームを作成します。

import random

WORDLIST_FILENAME = "words.txt"

def loadWords():   

    """   
    単語のリストを返してください。単語は、小文字の文字列です。
    単語リストの量によっては、この関数が終了するまでに時間がかかる場合があります。

    """ 

    print("Loading word list from file...")   
    inFile = open(WORDLIST_FILENAME, 'r')   
    line = inFile.readline()   
    wordlist = line.split()   
    print("  ", len(wordlist), "words loaded.")   
    return wordlist

def chooseWord(wordlist):
    """
    wordlist (list): list of words (strings)
    ランダムな単語のリストを返してください。
    """
    return random.choice(wordlist)

wordlist = loadWords()

def isWordGuessed(secretWord, lettersGuessed):
    '''
    secretWord: ユーザが推測する単語
    lettersGuessed: これまでに推測された文字リスト
    returns: boolean, secretWordの全ての文字がlettersGuessedに含まれている場合はTrue

      そうでない場合は、False

    '''
    for i in secretWord:
        if i not in lettersGuessed:
            return False
    return True

def getGuessedWord(secretWord, lettersGuessed):
    '''
    secretWord: 文字列、ユーザーが推測する単語
    lettersGuessed: これまでに推測された文字リスト
    returns: 文字とアンダースコアで構成される文字列
     これまでにsecretWordのどの文字が推測されたかを表す
    '''
    result = [ ]
    for i in secretWord:
        if i in lettersGuessed:
            result.append(i)
        else:
            result.append('_')
    return ''.join(result)

import string
alph = string.ascii_lowercase

def getAvailableLetters(lettersGuessed):
    '''
    lettersGuessed: これまでに推測された文字リスト
    returns: まだ推測されていない文字を表す文字で構成された文字列

    '''
    remain = [ ]
    for i in alph:
        if i not in lettersGuessed:
            remain.append(i)
    return ''.join(remain)

def hangman(secretWord):
    '''
    secretWord: 文字列、推測するための秘密の単語
    ハングマンのインタラクティブなゲームを開始します。
    * ゲームの開始時に、ユーザーに secretWord に含まれる文字数を知らせます。
    * ユーザーには、1 ラウンドにつき 1 つの推測文字を提供するよう求めます。
    * ユーザーは、各推測の直後に、自分の推測がコンピュータの単語に含まれているかどうかのフィードバックを受け取る必要があります。
    * 各ラウンドの後、ユーザーには、これまでに部分的に推測された単語と、ユーザーがまだ推測していない文字も表示する必要があります。
    '''
    print("Welcome to the game, Hangman!")
    print("I am thinking of a word that is", len(secretWord), "letters long.")
    mistakesMade = 0
    lettersGuessed = [ ]

    while 8 - mistakesMade > 0:
        if isWordGuessed(secretWord, lettersGuessed) == True:
            print("------------")
            print("Congratulations, you won!")
            break
        else:
            print("------------")
            print("You have", 8 - mistakesMade, "guesses left.")
            print("Available letters:", getAvailableLetters(lettersGuessed))
            guess = str(input("Please guess a letter:")).lower()
            if guess in secretWord and guess not in lettersGuessed:
                lettersGuessed.append(guess)
                print("Good guess:", getGuessedWord(secretWord, lettersGuessed))
            elif guess in lettersGuessed:
                print("Oops! You've already guessed that letter:", getGuessedWord(secretWord, lettersGuessed))
            elif guess not in secretWord:
                print("Oops! That letter is not in my word:", getGuessedWord(secretWord, lettersGuessed))
                lettersGuessed.append(guess)
                mistakesMade += 1
        if 8 - mistakesMade == 0:
            print("------------")
            print("Sorry, you ran out of guesses. The word was", secretWord)
            break
        else:
            continue


secretWord = chooseWord(wordlist).lower()hangman(secretWord)

 

Midterm Exam

中間試験となるこの Midterm Exam は、ある期間内ならいつでも受けられます。問題はランダムで出されるようですが、その難しさは一定とのことです。制限時間は8時間で、開始したら終わるまで通しでおこなわなければなりません。実際にプログラムを書くのは3題ありました。正解まですぐにたどり着けばいいですが、こんがらがるとなかなかきついです。

ですが、これまでのプログラムをみてもらえばわかる通り、事前に説明やヒントが書かれています。問題には、def PROGRAM_NAME(object): で書いてね!と説明があり、さらにどのような解を返すものであるべきかが書かれています。自分が受けた時は以下の3題が出題されました。

"""
Problem 4

aListに含まれる文字列のうち、4文字以下のサブリストを返すPython関数を書いてみましょう。例えば、aList = ["apple", "cat", "dog", "banana"] の場合、関数は["cat", "dog"]のように返す必要があります。
この関数は、文字列のリストを受け取り、文字列のリストを返します。aListを変更してはいけません。
"""
def lessThan4(aList):
    bList =
    for i in range(len(aList)):
        if len(aList[i]) <=3:
            bList.append(aList[i])
    return bList

 

"""
Problem 5

aDict内のキーのリストを返すPython関数を書いてください。そのkeyは固有な整数値に対応しています。返したkeyのリストは昇順にソートされていなければなりません。(aDictに固有な値が含まれていない場合は、空のリストを返す必要があります)。
"""
def uniqueValues(aDict):
    tmp = {}
    result =
    for value in aDict.values():
        if(value in tmp.keys()):
            tmp[value] += 1
        else:
            tmp[value] = 1
    for key in aDict.keys():
        if(tmp[aDict[key]] == 1):
            result.append(key)
return sorted(result)

 

"""
Problem 6

リストを平滑化する関数を書いてください。リストには他のlist、str、またはintが含まれます。例えば、[[1,'a',['cat'],2],[[[3]],'dog'],4,5]は、[1,'a','cat',2,3,'dog',4,5]に平滑化されます。
"""
def flatten(aList):
    newList = []
    for item in aList:
        if type(item) != list:
            newList.append(item)
        else:
            newList.extend(flatten(item))
    return newList

 

前半戦いかがだったでしょうか。正直なところ、この全てが当時できたわけではなく、今回改めてこのBlogに書こうとした時に書き直したものもあります。さらには知人に聞いたり、ネットで調べたりかなりしました。ただ、このedXのいいところは、自分で考えなければならない場所がある、というところです。論理性がものをいうプログラミングにおいて、本当に自分の頭を使って考えることができるようになります。

次回は後半戦の、Unit 4から Final Exam を記載しようと思います。

コードが引用を使って書いたので見辛かったらすいません。デバイスによっては改行されてしまい、インデントがおかしくなると思われます。ご参考までに。

 

f:id:KenSuzuki1:20210211005354p:plain