2012年5月31日木曜日

TopCoder SRM393 Div2 250Pts

このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。問題文について説明する。

道を安全なものにするために、ある地域の政府は時間によって複数の速度制限を設けることにした。混雑時には危険な事故を避けるため、速度制限は厳しいものになる。あなたは、ある単位距離だけ運転する必要があり、どの程度の時間がかかるか知りたいと思っている。問題では、速度制限を意味するspeedLimit[]という整数型の配列が与えられる。(0を基準とした添え字で)要素iの内容はある時刻iからi+1の単位時間における速度制限である。speedLimit[]は1日の速度制限の様子を表しており、このパターンは繰り返されることになる(1日経過して速度制限の内容は配列の先頭に戻る)。あなたは時刻0から運転を開始するものとし、運転中は速度制限の上限で常に運転を行うものとする。journeyLengthという距離だけ走った時の、運転の平均速度を返すメソッドを作成せよ。

私の解答はこちら。

public class VariableSpeedLimit {

 public double journeyTime(int journeyLength, int[] speedLimit) {
  int idx = 0; // 走っている時点での速度制限配列の添字管理
  double time = 0.0; // 走行時間
  int patternLength = speedLimit.length;
  int totalRun = 0;
  while( true ){
   if( totalRun + speedLimit[idx] < journeyLength ){ // 次の単位時間も継続して走る場合
    totalRun += speedLimit[idx];
    time += 1.0;
   }else{ // 次の単位時間中に走り終える場合
    time += (journeyLength - totalRun)*1.0 / speedLimit[idx];
    break;
   }
   idx = (idx + 1) % patternLength; / 速度制限の上限値を変更する
  }
  return time;
 }

}

得点は233.63/250、1回のsubmitでシステムテストクリア。中央値は約187点。

2012年5月30日水曜日

初めてのコンピュータサイエンス第10章解答

第10章の解答。以下ネタバレなので、読みたくない方は立ち去りましょう。問題文は載せませんので悪しからず。必要なら買いましょう。その前にこの章の個人的なメモ。

  • pythonにおけるリストのコピーはList[:]のように、全体をスライシングする書き方にすればよい。

1

a)b)の解答

空の文字列を用意して、AであればT、TであればA、GであればC、CであればGを結合することを文字列の末尾まで続ける。

c)の解答

def complement(sequence):
    ret = ''
    for c in sequence:
        if c == 'A':
            ret += 'T'
        elif c == 'T':
            ret += 'A'
        elif c == 'G':
            ret += 'C'
        elif c == 'C':
            ret += 'G'

    return ret

if __name__ == '__main__':
    print complement('AATTGCCGT')

2

a)~c)までまとめて解答。a)の解答はmin_index関数の内部そのものになります。また、引数にboolというものを取れいう指示があるのですが、boolは予約語なので、booleanに変更。

def min_index(sequence):
    idx = 1
    val = sequence[0]
    for i in range(2, len(sequence)):
        if sequence[i] < val:
            val = sequence[i]
            idx = i
    return tuple((val, idx))

def max_index(sequence):
    idx = 1
    val = sequence[0]
    for i in range(2, len(sequence)):
        if sequence[i] > val:
            val = sequence[i]
            idx = i
    return tuple((val, idx))

def min_or_max_index(sequence, boolean):
    if boolean == True:
        return max_index(sequence)
    else:
        return min_index(sequence)

if __name__ == '__main__':
    data = [3, 7, 2, 0, 23.1, 1.4, 9]
    print min_index(data)
    print min_or_max_index(data, False)
    print min_or_max_index(data, True)

3

どこまでを仕様とするかにも依るが、面白いリストには、例えば長さ0や長さ1のリスト、最小値が先頭にあるリスト、文字列を含むリストというのも考えられる。最小値が先頭にある場合は、初期設定で最小値を先頭の値としている場合に対応するためのテストである。以下のコードでは、前提として、長さが1以上、文字列は一切含まないものとしてテストを行うものである。ex10_2は2番のコードである。

import nose
from ex10_2 import min_index

def test_min_index():
    data = [1, 100]
    assert min_index(data) == tuple((1, 0))
    data = [3]
    assert min_index(data) == tuple((3, 0))

if __name__ == '__main__':
    test_min_index()

4

最小の2つの要素を探すのに、0または1つの要素からなるリストを与えられた場合は、そのようなものは「ない」ということで、Noneを返す。もしくは添字アクセスに失敗することから、例外を返すというのが考えられる。はじめの先頭2要素の比較で、アクセスしようとしている添字が存在していないことが問題になることに注意。

2012年5月29日火曜日

初めてのコンピュータサイエンス第9章解答

第9章の解答。以下ネタバレなので、読みたくない方は立ち去りましょう。問題文は載せませんので悪しからず。必要なら買いましょう。その前にこの章の個人的なメモ。

  • setオブジェクトで保持される順序にルールはない。
  • 集合はハッシュテーブルというデータ構造に格納される。
  • 集合の要素に対し、ハッシュコードが計算される。ハッシュコードはイミュータブル(書き換え不可能なデータ)のみ持つことが許される。
  • 辞書の初期化は{}で行う。追加はappendなどではなく、辞書名[キー] = 値 という形式で指定すればOK。
  • 185ページのdict_of_dicts.pyのサンプルコードに登場する辞書でJグドールに関する項目に'霊長類研究者'(英語では'primate researcher')とあるが、この後ろに「,」がないため、編集の必要がある。おそらくバグ。

1

# -*- encoding: sjis -*-

def find_dups(data):
    h_table = {}
    for d in data:
        if d in h_table.keys(): # getメソッドを利用する方法もある
            h_table[d] += 1
        else:
            h_table[d] = 1
    ret = []
    # iteritemsはオブジェクトのコピーを作らないので高速に動かすことができる
    for (key, value) in h_table.iteritems():
        if value >= 2:
            ret.append(key)
    return ret

if __name__ == '__main__':
    data = range(10) + range(10, 5, -1) + range(3, 7)
    ret = find_dups(data)
    print ret

2

def mating_pairs(males, females):
    ''' the size of males and that of females are the same. '''
    ret = []
    # while males: is OK. this answer is a bit copmlex.
    while len(males) > 0:
        ret.append((males.pop(), females.pop()))
    return set(ret)

if __name__ == '__main__':
    males = set(['A', 'B', 'C', 'D', 'E'])
    females = set(['1', '2', '3', '4', '5'])
    print mating_pairs(males, females)

3

PDB形式のAUTHORの行に関する情報はこちらのpdfを参考にするとよいでしょう。人物名はコンマ区切り、AUTHORと人名は空白で区切られているという条件を使います。また、最後にコンマがあり人名が続かないこともありますので、そのようなことも考慮しています。

# -*- encoding: sjis -*-

import sys

def read_author(r):
    ret = set()
    for line in r:
        if not line:
            continue
        if line[:6].upper() != 'AUTHOR': # AuthorなどもOKにするため、upper()を挟んでいる
            continue
        # 仕様の都合上8文字目から作者名が始まる可能性がある。
        # strip()でいったん両端の空白を削除してから","で区切る
        line = line[7:].strip().split(",")
        print line
        for i in range(len(line)):
            if not line[i]: # AUTHORとあるが、何も続かない場合
                continue
            ret.add(line[i])
    return ret # setを返しておく

if __name__ == '__main__':
    names = set()
    for filename in sys.argv[1:]: # 外部からファイルを読み込みたい
        infile = open(filename, 'r')
        name = read_author(infile)
        names = names.union(name) # 和集合はunionである
        infile.close()
    print names

4(自信薄)

setの中に中身が変更可能なsetが入れられないのでfrozensetにして入れている。vowelは要素にfrozensetのデータを持つが、すでに通常のsetとして扱って問題ない。中身が書き換え可能なメモリアドレスにvowelsが配置されるということになる。

5

def count_values(dic):
    values = {}
    for (key, value) in dic.iteritems():
        if not value in values:
            values[value] = 1
    return len(values)

if __name__ == '__main__':
    print count_values({'red':1, 'green':2, 'blue':3})
    print count_values({'red':1, 'green':2, 'blue':1})
    print count_values({'red':2, 'green':2, 'blue':2})

6

def min_elementary_particle(dic):
    minimum = 1.1 # probability is always smaller than 1
    elem = ''
    for (key, value) in dic.iteritems():
        if value < minimum:
            minimum = value
            elem = key
    return elem

if __name__ == '__main__':
    component = {'neutrino':0.14 , 'neutron':0.55,
                 'proton':0.21, 'meson':0.03, 'muon':0.07}
    print min_elementary_particle(component)

7

def count_duplicates(dic):
    dup = {}
    for (key, value) in dic.iteritems():
        if not value in dup:
            dup[value] = 1
        else:
            dup[value] += 1

    dup_list = []
    for (key, value) in dup.iteritems():
        if value >= 2:
            dup_list.append(key)
    return len(dup_list)

if __name__ == '__main__':
    color = {'red':1, 'green':4, 'blue':2, 'orange':3, 'green':2, 'orange':6}
    print count_duplicates(color) # 2 is duplicated number.

8

例外という先の内容を無理やり利用しろということなので、試しに使ってみた。

def fetch_and_set(dic, key, new_value):
    if key in dic:
        old_value = dic[key]
        dic[key] = new_value
        return old_value
    else:
        raise KeyError("Unable to replace value for nonexistent key")

if __name__ == '__main__':
    color = {'red':1, 'green':4, 'blue':2, 'orange':3}
    print fetch_and_set(color, 'green', 100) # 4
    try:
        fetch_and_set(color, 'black', 3) # KeyError exception
    except KeyError:
        print "KeyError occurred!"

9

問題の仕様にはないのですが、辞書には必ずしもキーがR、G、Bだけではないものと仮定します。RGB以外は無視するものとします。

def is_balanced(dic):
    total = 0
    for (key, value) in dic.iteritems():
        if key == 'R' or key == 'G' or key == 'B':
            total += value

    if abs(total - 1.0) < 10 ** -15: # almost equal to 1
        return True
    else:
        return False

if __name__ == '__main__':
    color = {'R':0.1, 'G':0.4, 'B':0.5}
    print is_balanced(color) # True
    color = {'R':0.1, 'G':0.4, 'X':0.2, 'B':0.5}
    print is_balanced(color) # True
    color = {'R':0.1, 'G':0.4, 'B':0.2}
    print is_balanced(color) # False

10

両方の辞書に同じキーと同じ値が含まれている対のみ返します。同じキーだが値が違うという場合はdict_intersectの返り値の辞書には含まないものとします。

def dict_intersect(dic1, dic2):
    k2 = dic2.keys()
    ret = {}
    for (k1, v1) in dic1.iteritems():
        if k1 in k2 and v1 == dic2[k1]:
            ret[k1] = v1
    return ret

if __name__ == '__main__':
    c1 = {'red':1, 'green':4, 'blue':2, 'orange':3, 'green':2, 'orange':6}
    c2 = {'red':1, 'green':5, 'blue':2, 'yellow ':3}
    print dict_intersect(c1, c2) # blue and red are extracted

11

scientists = {
  'jgoodall'  : {'surname'  : 'Goodall',
                 'forename' : 'Jane',
                 'born'     : 1934,
                 'died'     : None,
                 'notes'    : 'primate researcher', # distributed sample code lacks comma.
                 'author'   : ['In the Shadow of Man', 'The Chimpanzees of Gombe']},
  'rfranklin' : {'surname'  : 'Franklin',
                 'forename' : 'Rosalind',
                 'born'     : 1920,
                 'died'     : 1957,
                 'notes'    : 'contributed to discovery of DNA'},
  'rcarson'  : {'surname'  : 'Carson',
                 'forename' : 'Rachel',
                 'born'     : 1907,
                 'died'     : 1964,
                 'notes'    : 'raised awareness of effects of DDT',
                 'author'   : ['Silent Spring']}
}

def db_headings(dic):
    ret = []
    for values in dic.values():
        ret += values.keys()
    return set(ret)

if __name__ == '__main__':
    print db_headings(scientists)

12

scientistsは上のデータを利用することにします。rfranklinは他の二つとキーが異なるため内部の辞書は常に一定にはなりません。そのため、db_consistent関数にscientistsを渡すと、Falseになります。if elem.symmetric_difference(set(values)):は要素数が0でなければという意味になります。

def db_consistent(dic):
    first = dic.keys()[0]
    elem = set(dic[first].keys())
    for values in dic.values():
        if elem.symmetric_difference(set(values)):
            return False
    return True

if __name__ == '__main__':
    print db_consistent(scientists)

13

空行で機能が大まかに区切られているので、それを1つのまとまりとしてモジュールにするというだけですね。

import sys

def create_dic(files):
    count = {}
    for filename in sys.argv[1:]:
        infile = open(filename, 'r')
        for line in infile:
            name = line.strip()
            count[name] = count.get(name, 0) + 1
        infile.close()
    return count

def reverse_dict(dic):
    freq = {}
    for (name, times) in dic.iteritems():
        print name, times
        if times in freq:
            freq[times].append(name)
        else:
            freq[times] = [name]
    return freq

def print_dic(dic):
    for key in sorted(dic):
        print key
        for name in dic[key]:
            print ' ', name

if __name__ == '__main__':
    dic = create_dic(sys.argv[1:])
    r_dic = reverse_dict(dic)
    print_dic(r_dic)

14

a)、b)の解答は以下の通り。

def sparse_add(dic1, dic2):
    ret = dic1.copy()
    keys = set(dic1.keys() + dic2.keys())
    for key in keys:
        ret[key] = 0
        if key in dic1.keys():
            ret[key] += dic1[key]
        if key in dic2.keys():
            ret[key] += dic2[key]
    return ret

def sparse_dot(dic1, dic2):
    ret = 0
    for (key, value) in dic1.iteritems():
        if key in dic2:
            ret += value * dic2[key]
    return ret

if __name__ == '__main__':
    v1 = {0:1, 6:3, 7:-1}
    v2 = {1:1, 2:2, 6:1, 7:-1}
    print sparse_add(v1, v2) # {0: 1, 1: 1, 2: 2, 6: 4, 7: -2}
    print sparse_dot(v1, v2) # 4

c)に関しては、疎ベクトルの長さが、辞書の長さになるのか、それとも最後に現れた辞書のキーの値+1になるのかということが曖昧になっている。0を値に持つキーをどのように扱うかということが、「疎ベクトルの長さ」という言葉だけでははっきりしないということである。

2012年5月28日月曜日

英単語学習記録20120528

英単語 意味
drop by立ち寄る
in low spirits意気消沈する
herd群れ、群衆、(群れを)集める
take charge of~の世話を引き受ける
portion部分、割り当て
compassion思いやり
nonethelessそれでもやはり
chronicle記録する
indispensable必須の、欠かせない
premise前提
troop部隊、群れ
crucial特に重要な
jargon専門用語、業界用語
endorse推薦する
string of一連の
official職員
appliance電化製品
perimeter周囲
congestion混雑
distribution流通、分布
vast広大な、膨大な
relocate~を移転する
dispatch発送する
in accordance with~~に従って
legitimate正当な
courteous礼儀正しい、丁寧な
excerpt抜粋
be up to~~を遂行することができる
rewardingやりがいのある
perplexed困った、途方に暮れた(be at a lossと同じ)
come up発生する(ariseと同じ)

2012年5月26日土曜日

初めてのコンピュータサイエンス第8章解答

第8章の解答。以下ネタバレなので、読みたくない方は立ち去りましょう。問題文は載せませんので悪しからず。必要なら買いましょう。その前にこの章の個人的なメモ。

  • ファイルを読み込む際は関数の外でファイルのオープン・クローズを行うとよい。これは処理を1つの関数だけで済ませることができるためである。Webページやストリームなどを統一的に扱える。
  • ファイルの追加はopenする際の引数に'a'と与える
  • pp.161の注釈は「単一のタプルが返されている」ではなく、「単一のリストが返される」が正しい。おそらく誤植。

1

後ろから前に向かってファイル全体を読み出すという意味をどう捉えるかが問題になりそうですが、行だけ後ろから前へと見るか、行の中身まで反転させるか悩ましいところではあります。今回は前者で考えています。

def read_reverse(file):
    rev = []
    for line in file:
        rev.insert(0, line)
    for line in rev:
        print line,

if __name__ == '__main__':
    f = open('data.txt', 'r')
    read_reverse(f)

2

タプルのタプルの方が扱いやすいのは、意味的なまとまりで区切っているためである。今回のコードでは、日付、緯度、経度、天気情報という意味でまとまっているので、データへのアクセスが単純化できる(経度は何番目だっけ?などと悩むことは減るだろう)。実は問題の解答がオライリーから提供されているが、誤りのように思われる。fieldsがタプルのタプルでないとループが適切に動かないためである。コード中の中で呼び出しているテキストファイルは提供されていないので、関数のコメントにある仕様に沿って作成する必要がある。

def read_weather_data(r):
    '''Read weather data from reader r in fixed-width format.
    The field widths are:
        4,2,2   YYYYMMDD (date)
        2,2,2   DDMMSS   (latitude)
        2,2,2   DDMMSS   (longitude)
        6,6,6   FF.FFF   (temp, deg. C; humidity, %; pressure, kPa)
    The result is a tuples of tuples,
 where each tuple is of the form:
    ((YY, MM, DD), (DD, MM, SS), (DD, MM, SS), (Temp, Hum, Press))'''
    fields = (((4, int), (2, int), (2, int)),       # date
              ((2, int), (2, int), (2, int)),       # latitude
              ((2, int), (2, int), (2, int)),       # longitude
              ((6, float), (6, float), (6, float))) # data
    result = []
    for line in r:
        start = 0
        for grp in fields:
            record = []
            for (width, target_type) in grp:
                text = line[start:start+width]
                field = target_type(text)
                record.append(field)
                start += width
            result.append(tuple(record))
    return result

if __name__ == '__main__':
    f = open('ex08_2_data.txt', 'r')
    ret = read_weather_data(f)
    print ret

3

# -*- encoding: sjis -*-
''' fieldが固定幅の場合、先頭からの位置の場合のどちらにも対応'''

def read_weather_data(r, fields):
    result = []

    for line in r:
        start = 0
        a_line = []
        for (width, target_type) in fields:
            text = line[start:start+width]
            field = target_type(text)
            a_line.append(field)
            start += width
        result.append(tuple(a_line))
    return result

def transform_fields(fields, last_idx):
    res = []

    for i in range(len(fields)):
        if i != len(fields)-1:
            width = fields[i+1][0] - fields[i][0]
        else:
            width = last_idx - fields[i][0]
        res.append((width, fields[i][1]))
    return(tuple(res))

def wrapper_function(data, fields):
    ''' 先頭の幅に関する値で入力のfieldの種類がどちらか判別する。
        0ならば、いったんfieldsを変換してread_weather_dataに入れる。
        これによりread_weather_dataの引数は1つ増えることになる。
    '''
    if fields[0][0] == 0:
        # 38はハードコードだが、幅の値は仕様であり、既知とする。
        fields = transform_fields(fields, 38)
    ret = read_weather_data(data, fields)
    return ret

if __name__ == '__main__':
    f = open('ex08_2_data.txt', 'r')
    '''
    fields = ((4, int), (2, int), (2, int),       # date
              (2, int), (2, int), (2, int),       # latitude
              (2, int), (2, int), (2, int),       # longitude
              (6, float), (6, float), (6, float)) # data
    '''
    fields = ((0, int),    (4, int),    (6, int),    # date
              (8, int),    (10, int),   (12, int),   # latitude
              (14, int),   (16, int),   (18, int),   # longitude
              (20, float), (26, float), (32, float)) # data
    ret = wrapper_function(f, fields)
    print ret

4,5(2問同時解答)

continueを利用することにより、インデントの数が減るので目を動かす量が減り、読みやすさは向上するものと思われる。

# -*- encoding: sjis -*-
import sys
import tsdl

def smallest_value(r):
    line = tsdl.skip_reader(r).strip()
    if not line:
        return -1 # something error occurred.
    smallest = int(line)

    for line in r:
        line = line.strip()
        if line == '-':
            continue
        value = int(line)
        if value < smallest:
            smallest = value

    return smallest

if __name__ == '__main__':
    input_file = open(sys.argv[1], 'r')
    print smallest_value(input_file)
    input_file.close()

6

以下のコードに登場するmultimol3.pdbは、通常のpdbに対し、CMNTで始まるコメント行やタブやスペースのみからなる空白の行が含まれたファイルになります。訳者のコードでは動かし方が分かりにくいので、メソッド名は採用しておりますが、1から書き直しています。

# -*- encoding: sjis -*-

def read_all_molecules(r):
    result = []
    reading = True
    while reading:
        molecule = read_molecule(r) # COMPNDという行からENDという行まで読む
        if molecule:
            result.append(molecule)
        else:
            reading = False
    return result

def get_line(r):
    ''' 空白やコメントでない行を返す。rは返す行の次の行の先頭に向かう '''

    while True:
        line = r.readline() # とりあえず1行読んで
        if not line: # 最後に来たら終了
            break
        line = line.strip() # 前後の空白を取り除いて
        if not line: # 空白ならばタブやスペースのみからなる行なので処理を続行
            continue
        elif line.startswith('CMNT'): # コメントであっても続行
            continue
        else: # それ以外はPDBファイルに必要な行である
            return line
    return ''

def read_molecule(r):
    line = get_line(r)
    if not line:
        return None

    key, name = line.split()
    molecule = [name]
    reading = True

    while reading:
        line = get_line(r)
        if line.startswith('END'):
            reading = False
        else:
            key, num, typ, x, y, z = line.split()
            molecule.append((typ, x, y, z))
    return molecule

if __name__ == '__main__':
    f = open('multimol3.pdb', 'r')
    ret = read_all_molecules(f)
    f.close()
    print ret

7

本来であれば、原子のシリアルナンバーが1ずつ大きくなっていない場合、プログラムの実行者に対し、何も結果を返さず、エラーを明示的に出してやるのがよい。途中まで出してそれを表示するということも考えられるが、正常終了に見えてしまうため、問題があるということを隠してしまうことになるので、そのような処理にしないほうがよいものと思われる。ただし、以下のコードではエラーの出し方が本テキスト読書中時点でははっきりしない(例外を投げてしまうのが一番よさげなのだが、例外の利用方法を知らない)ため、print文でエラーメッセージを出しつつ、途中で処理を打ち切るようにしている。この場合、途中までの結果が返されることになる。改めて解答しなおすことになりそうですが、ひとまず載せることにします。

# -*- encoding: sjis -*-

def read_all_molecules(r):
    result = []
    reading = True
    while reading:
        molecule = read_molecule(r) # COMPNDという行からENDという行まで読む
        if molecule:
            result.append(molecule)
        else:
            reading = False
    return result

def get_line(r):
    while True:
        line = r.readline()
        if not line:
            break
        line = line.strip()
        if not line: # 空白ならば続行
            continue
        elif line.startswith('CMNT'):
            continue
        else:
            return line
    return ''

def read_molecule(r):
    line = get_line(r)
    if not line:
        return None

    print line
    key, name = line.split()
    molecule = [name]
    reading = True
    check_num = 1
    ret_mol = True

    print "line = ", line
    while reading:
        line = get_line(r)
        if line.startswith('END'):
            reading = False
        else:
            print "!", line
            key, num, typ, x, y, z = line.split()
            if int(num) != check_num:
                print "serial number error in %s!" % molecule[0]
                return None # Noneとすることで続きの処理が行われなくなる
            check_num += 1
            molecule.append((typ, x, y, z))
    return molecule

if __name__ == '__main__':
    f = open('multimol4.pdb', 'r') # ファイルは適当にいじっておくように。
    ret = read_all_molecules(f)
    f.close()
    print ret

2012年5月25日金曜日

TopCoder SRM392 Div2 250Pts

このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。問題文について説明する。

2007年の1月にお菓子屋さんが飴を製造した。毎月の最後の日に、お母さんは子供にいくつか飴を食べることを許している。飴の寿命は1/1から飴が食べられるまでの日数である。例えば、1/31に食べられた飴の寿命は31日、12/31に食べられた飴の寿命は365日である(うるう年でないことに注意!)。eatenCandies[]という2007年の各月の最後に食べられた飴の数が与えられたとき(配列の添字0は1月、添字1は2月を表す。以下同様)、飴の平均寿命を計算して返すメソッドを作成せよ。

私の解答はこちら。

public class AverageCandyLifetime {

 public double getAverage(int[] eatenCandies) {
  int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 各月の日数
  int sum = 0;
  int lifetimes = 0;
  int nCandies = 0;
  for( int i=0 ; i<eatenCandies.length ; i++ ){
   lifetimes += days[i];
   nCandies += eatenCandies[i];
   sum += eatenCandies[i] * lifetimes;
  }
  return (double)sum/nCandies;
 }

}

得点は244.91/250、1回のsubmitでシステムテストクリア。中央値は約215点。

2012年5月23日水曜日

TopCoder SRM391 Div2 250Pts

このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。問題文について説明する。

中国北部では豪雪で苦労している。豪雪により、中国の南北を結ぶ重要な高速道路が閉鎖された。あなたは豪雪に覆われた高速道路の地域の始点と終点についていくつかの報告を受けた。始点と終点が整数型の配列として与えられたとき、雪で覆われた道路の距離の合計を返すメソッドを作成せよ。なお、報告では領域が重複していることもあることに注意せよ。

私の解答はこちら。

public class SnowyWinter {

 public int snowyHighwayLength(int[] startPoints, int[] endPoints) {
  int size = 10000;
  boolean[] isCoveredSnow = new boolean[size]; // trueの数が雪で覆われた道路の距離になる
  for( int i=0 ; i<startPoints.length ; i++ ){
   for( int j=startPoints[i] ; j < endPoints[i] ; j++ ){
    isCoveredSnow[j] = true; // 雪で覆われている領域とする
   }
  }
  int len = 0;
  for( int i=0 ; i<size ; i++ ){
   if( isCoveredSnow[i] ) len++;
  }
  return len;
 }

}

得点は244.48/250、1回のsubmitでシステムテストクリア。条件で与えられているサイズの上限を与えずに解けると文句なしなのですがね。

フォロワー

ページビューの合計