読者です 読者をやめる 読者になる 読者になる

Cafe capybara TECH-BLOG

PHPな会社でゴリゴリしてるあかいいぬの技術ブログです

paizaのオンラインハッカソンに参加してみた

お久しぶりです。最近またコーディング時間が増えてきたので、ちょくちょく記事書こうかなと思います。

ニコマガの方が実はメインだったのですが、ちょっとグーグラビリティが低いかなと思ったので、技術系記事はこっちに書こうと。



以前もやっていたオンラインハッカソン
新人女子プログラマの書いたコードを直すだけの簡単なお仕事です!|paizaオンラインハッカソンVol.1
には私も参加したのですが(結果は散々)、先日その第二弾が開始されたらしいので、また参加してみました。

Pythonで。

ほぼ初体験の言語です。


将来的にはデータ分析のお仕事が出来ればなと思っていて、分析に有用だといわれている言語が汎用言語(CとかJavaとかPHPとか)の中ではこのPythonさんが一番という話を聞いて、勉強がてらいじってみました。


で、そのハッカソンのページは↓
女子大生とペアプロするだけの簡単なお仕事です!|paizaオンラインハッカソンVol.2

元々paizaというページは、Web上で簡単なバッチ処理の課題が与えられ、それに対応したソースコードを提出して採点してもらい、自分のコーディング能力を定量化、そして企業にオファーをもらう、という就職支援サイト的な意味合いがあるのですが、そこでの宣伝イベントですね。


ハッカソンってのは、短期間でプログラマーが共同していろいろ競ったりする「ハック+マラソン」の造語。


内容に関しては該当ページを見てもらえれば良いと思いますが、ここでは私の書いたコードを紹介。


class SearchWidgetPlace:
    def __init__(self):
        self.get_from_raw_input()
        #self.get_from_file("input1.txt")
        self.set_data()

        self.available_list = {}
        self.make_list()

    # 標準入力から文字列を取得
    def get_from_raw_input(self):
        self.input_string = ""
        try:
            while True:
                self.input_string += raw_input() + "\n"
        except:
            pass

    # ファイルから文字列を取得(デバッグ用)
    def get_from_file(self, file_name):
        f = open(file_name, 'r')
        self.input_string = f.read()
        f.close()

    # 各種変数を設定
    def set_data(self):
        height_length = self.input_string.index(' ')
        self.home_height = int( self.input_string[ 0 : height_length ] )

        width_length = self.input_string.index('\n')
        self.home_width = int ( self.input_string[ height_length + 1 : width_length] )

        self.situation = self.input_string.replace( str(self.home_height) + ' ' + str(self.home_width) + "\n", "", 1).split("\n", self.home_height)

        self.widget_count = int ( self.situation[self.home_height][ 0 : self.situation[self.home_height].index("\n") ] )
        self.widgets = self.situation[self.home_height].replace(str(self.widget_count) + "\n", "", 1).split("\n", self.widget_count)

    # その座標にウィジェットを置けるかどうか
    def is_open(self, y, x):
        return 0 == int(self.situation[y][x])

    # その座標におけるウィジェットのサイズ一覧をリストに追加
    # 名前は残念
    def adoptive_search(self, base_y, base_x):
        max_x = self.home_width - base_x
        for add_y in range(0, self.home_height - base_y):
            if not self.is_open(base_y + add_y, base_x):
                # Y方向はもうない
                return
        
            for add_x in range(0, max_x):
                if self.is_open(base_y + add_y, base_x + add_x):
                    # (base_x, base_y)~(base_x + add_x, base_y + add_y)のブロックは置ける
                    width = str(add_x + 1)
                    height = str(add_y + 1)

                    # このdict判定が一番キモい
                    if not height in self.available_list:
                        self.available_list[height] = {width: 1}
                    elif not width in self.available_list[height]:
                        self.available_list[height][width] = 1
                    else:
                        self.available_list[height][width] += 1
                else:
                    # X方向はもうない
                    max_x = add_x
                    break

    # 全座標の置けるかどうかリストを作成
    def make_list(self):
        for base_y in range(0, self.home_height):
            for base_x in range(0, self.home_width):
                self.adoptive_search(base_y, base_x)

    # 検索結果の文字列を取得
    def get_result_text(self):
        result = ""
        for widget in self.widgets:
            if not widget:
                continue

            height, width = widget.split(' ', 2)

            if height in self.available_list and width in self.available_list[height]:
                result += str(self.available_list[height][width])
            else:
                result += str(0)

            result += "\n"

        return result

searchWidgetPlace = SearchWidgetPlace()
result = searchWidgetPlace.get_result_text()
print result,

で、このコードの採点結果は↓
akai_inuさんの採点結果[85点] こ、この位で凄いなんて思わないんだから!|paizaオンラインハッカソンVol.2

最後のテストはクリア出来なかったが、まあ初めての言語にしては上出来かな、と。

Python 辞書型で詰まる

実際5時間弱(かけすぎ)で出来たと思いますが、一番詰まったのはやっぱり辞書型の扱いですね。

d = {'love': 'capy', 'so': 'capy', 'will': 'capy'}

見た感じjsonPHP連想配列と同じなのですが、これキーがないものを取得しようとするとエラーになるのよね。

で、辞書型の中にさらに辞書型を入れるとかってのも、javascriptPHPみたいにゆるくなくて、最初にちゃんと辞書型を宣言して入れてあげないといけない。

>>> d = {'ca': 'py'}
>>> d
{'ca': 'py'}

>>> d['ba'] = 'ra'
>>> d
# キーを追加するだけならOK
{'ca': 'py', 'ba': 'ra'}

>>> d['ca']['ba'] = 'ra'
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    d['ca']['ba'] = 'ra'
# strが入ってる所に辞書型追加は無理(ふつう)
TypeError: 'str' object does not support item assignment 

>>> d['a_bakkari']['sugoi'] = 'ne'
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    d['a_bakkari']['sugoi'] = 'ne'
# キーない所に辞書型追加はダメ(つらい)
KeyError: 'a_bakkari' 

いや、javascriptPHPのObjectさんがゆるゆるすぎるっていう見方の方が強いと思いますが、そういう言語をメインとしていじっている人間からすると面倒な部分でした。


ただ、こういったバッチ処理を書くのにはかなり良い言語ですね。やっぱりタブ認識型でセミコロンいらない言語は見てて気持ちいい。

# よく制御文あとのコロンを忘れるけどね