6
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

プログラミング問題集(問1〜問5)

Last updated at Posted at 2019-10-07

問1:和が m になる取り出し方

自然数 k1, k2, ..., kn が書かれた n 枚の紙片が袋に入っている。この袋から紙片を取り出し、数字を見て袋に戻すことを4回行う。その4つの数字の和が m になる取り出し方が存在するかどうか計算し、存在すれば True、 存在しなければ False と出力する関数を作成しなさい。

ただし、

  • n ≤ 50
  • 1 ≤ m ≤ 104
  • 1 ≤ ki ≤ 103

とする。

また、データ数が増加するに伴い計算時間がどう変化するか計測して確認しなさい。

【ヒント】 4重ループを作って総当たり検索をしましょう。ひとつでも存在が見つかればループから脱出してOK。

例1-1

n = 10
m =  36
k =  [13, 39, 63, 70, 18, 87, 46, 99, 68, 47]
False

例1-2

n = 10
m =  66
k =  [60, 45, 73, 100, 57, 82, 2, 85, 43, 8]
True

例1-3

n = 20
m =  496
k =  [240, 471, 143, 482, 231, 127, 482, 145, 195, 336, 31, 83, 450, 376, 108, 133, 118, 340, 400, 170]
True

例1-4

n = 20
m =  395
k =  [94, 143, 107, 262, 478, 446, 443, 373, 431, 36, 281, 476, 153, 23, 203, 279, 429, 476, 281, 475]
False

例1-5

n = 50
m =  3538
k =  [62, 770, 584, 150, 228, 872, 978, 735, 667, 620, 921, 254, 280, 811, 468, 541, 846, 586, 385, 151, 185, 522, 745, 941, 170, 885, 19, 246, 331, 383, 616, 436, 626, 320, 42, 572, 978, 42, 973, 648, 978, 926, 510, 918, 180, 517, 352, 724, 827, 424]
True

例1-6

n = 50
m =  5264
k =  [629, 873, 624, 235, 721, 979, 966, 370, 48, 817, 687, 766, 554, 966, 673, 134, 858, 876, 167, 838, 858, 576, 6, 417, 218, 120, 142, 800, 113, 912, 424, 548, 655, 134, 744, 587, 481, 284, 197, 542, 559, 16, 367, 241, 32, 268, 545, 930, 162, 978]
False

参考:例の作り方

import random
n = 50
m = random.randint(1, 10000)
k = [random.randint(1, 1000) for _ in range(n)]

print("m = ", m)
print("k = ", k)

問2:三角形は作れるか?

様々な長さの n 本の棒がある。棒 i の長さは ai とする。その中から3本を取り出し、できるだけ周長の長い三角形を作りたい。そのような三角形が存在するときは、最長の周長を出力し、存在しないときは 0 を出力する関数を作成しなさい。

ただし、

  • 3 ≤ n ≤ 100
  • 1 ≤ ai ≤ 103

とする。

また、データ数が増加するに伴い計算時間がどう変化するか計測して確認しなさい。

【ヒント】 3重ループで全探索しながら、最大値を見つけるたびに更新していく。

例2-1

n =  5
a =  [28.54, 13.36, 54.82, 13.91, 44.29]
127.65

例2-2

n =  4
a =  [24.73, 53.4, 0.25, 97.89]
0

例2-3

n =  19
a =  [493.13, 615.02, 340.68, 462.98, 988.55, 572.16, 572.91, 963.01, 12.07, 95.51, 733.24, 810.39, 105.99, 574.57, 945.38, 937.82, 976.24, 245.43, 260.06]
2927.8

例2-4

n =  93
a =  [5.12, 37.92, 423.29, 512.46, 801.74, 391.6, 149.55, 430.43, 310.78, 562.61, 11.39, 662.88, 872.17, 501.71, 187.24, 575.35, 512.01, 367.66, 196.64, 679.75, 174.56, 276.71, 737.98, 221.59, 734.84, 53.9, 125.24, 261.69, 780.83, 376.43, 985.84, 240.3, 256.35, 324.72, 964.01, 279.76, 13.02, 15.32, 307.18, 465.25, 291.69, 713.49, 125.53, 765.65, 38.57, 567.78, 402.4, 131.54, 288.23, 705.4, 351.75, 818.57, 176.69, 473.8, 598.14, 711.17, 576.65, 198.87, 52.31, 588.76, 722.02, 710.96, 119.23, 846.55, 595.7, 80.1, 307.05, 750.6, 485.46, 787.75, 474.98, 428.54, 369.85, 740.59, 262.23, 983.04, 808.89, 916.89, 753.5, 7.45, 716.17, 632.46, 217.93, 376.37, 15.16, 27.05, 321.26, 815.79, 514.78, 333.77, 394.86, 963.88, 824.96]
2932.89

参考:例の作り方

import random

n = random.randint(3, 100)
a = [round(random.random() * 1000, 2) for _ in range(n)]

print("n = ", n)
print("a = ", a)

問3:部分和問題

n 個の整数 a1, a2, ..., an を入力した時、その中からいくつか選び、その和が m にできれば True を、できなければ False を返す関数を作りなさい。

ただし、

  • 1 ≤ n ≤ 20
  • -104 ≤ ai ≤ 104
  • -104 ≤ m ≤ 104

とする。

また、データ数が増加するに伴い計算時間がどう変化するか計測して確認しなさい。

【ヒント】 問1と似てますが、いくつ選択するかが決まっていないという点で、違います。「深さ優先探索」を使う解法が知られています。

例3-1

n =  20
a =  [-36, 52, 24, 64, 16, -10, -44, 93, -37, -86, 100, 55, 77, -11, -62, 16, -14, -2, -57, 47]
m =  -83
True

例3-2

n =  20
a =  [31, -42, -45, 2, 39, -11, 62, -20, 8, 19, -78, -38, 12, 47, -6, 36, 24, -8, -16, -31]
m =  0
True

例3-3

n =  20
a =  [-1945, 4145, -2296, -2054, -3499, 3623, -9739, 9542, -9035, 3569, -3484, -455, 3324, -8746, -6922, -656, 8126, 3515, 4931, 4203]
m =  -5329
True

例3-4

n =  20
a =  [-7711, -4112, -1207, -2950, -4434, 2544, -5463, -1524, -8374, -9426, -1934, -2191, -8625, 7108, -7383, 4248, -930, 1616, -8065, -7854]
m =  -2009
False

参考:例の作り方

import random
n = 20
a = [random.randint(-10000, 10000) for _ in range(n)]
m = random.randint(-10000, 10000)

print("n = ", n)
print("a = ", a)
print("m = ", m)

問4:迷路の最短経路

大きさが X * Y (XYともに整数)の迷路が与えられます。迷路はスタート「S」とゴール「G」、通路「_」と壁「#」からできており、1ターンあたり、隣接する上下左右4マスの通路のいずれかに移動できます。スタートからゴールまで移動可能な場合は、必要な最小のターン数を返し、不可能な場合は False を返す関数を作りなさい。

ただし、

  • X, Y ≤ 100

とする。

また、データ数が増加するに伴い計算時間がどう変化するか計測して確認しなさい。

【ヒント】 「幅優先探索」を使う典型的な問題です。

例4-1

string_maze = \
    '__##_S______\n' \
    '##_##____##_\n' \
    '______#_____\n' \
    '#_#_#______#\n' \
    '__#______#_#\n' \
    '#______#___#\n' \
    '_#_##______#\n' \
    '___###__#__G\n' \
    '_###_____##_\n' \
    '_#__#_______\n'
13

例4-2

string_maze = \
    '__S#__#___##\n' \
    '_____#___###\n' \
    '__##__#__###\n' \
    '_#__##___#_#\n' \
    '_###_##____#\n' \
    '_____#_###__\n' \
    '________#_#_\n' \
    '#______#_#_#\n' \
    '#___#___#___\n' \
    '________#G__\n' 
False

例4-3

string_maze = \
    'S_#_##__###_\n' \
    '#___#__#__##\n' \
    '_##_______#_\n' \
    '___##__#_##_\n' \
    '___#__#_#___\n' \
    '#____#____#_\n' \
    '__#_##G####_\n' \
    '_____##___#_\n' \
    '____##__#___\n' \
    '#_#____##_#_\n' \
38

例4-4

string_maze = \
    '##___###_#_#\n' \
    '#___S###_#_#\n' \
    '##_#________\n' \
    '___#__##_#__\n' \
    '____##______\n' \
    '_#____#__##_\n' \
    '#___#_#____#\n' \
    '___________#\n' \
    '_#__#____#_#\n' \
    '#____#___###\n' \
    '__#_#_#_#___\n' \
    '#__##_#_#_#G\n' \
    '#__##_____##\n' \
    '#__#____#___\n' \
    '#__#_#__##_#\n' \
23

参考:例の作り方

import random

def generate_random_maze(X, Y):
    t = ("#", "_", "_")
    maze = []
    for y in range(Y):
        maze.append([random.choice(t) for x in range(X)])
    sx = random.choice(range(X))
    sy = random.choice(range(Y))
    gx = random.choice(range(X))
    gy = random.choice(range(Y))
    while (gx - sx) < X / 2:
        sx = random.choice(range(X))
        gx = random.choice(range(X))
    while (gy - sy) < Y / 2:
        sy = random.choice(range(Y))
        gy = random.choice(range(Y))        
    maze[sy][sx] = 'S'
    maze[gy][gx]= 'G'
    return maze

def stringize_maze(maze):
    str = ""
    for maz in maze:
        str += "".join(maz) + "\n"
    return str

string_maze = stringize_maze(generate_random_maze(12, 10))
print(string_maze)

問5:できるだけ少ない枚数の硬貨で支払いたい

財布の中に500円玉が n1 枚、100円玉が n2 枚、50円玉が n3 枚、10円玉が n4 枚、5円玉が n5 枚、1円玉が n6 枚あります。できるだけ少ない枚数の硬貨で、お釣りなしで x 円を支払いたいとき、必要な硬貨の枚数を返す関数を作りなさい。そのような支払い方ができない場合は False を返してください。

ただし、

  • 0 ≤ n1 ≤ 10
  • 0 ≤ n2 ≤ 10
  • 0 ≤ n3 ≤ 10
  • 0 ≤ n4 ≤ 10
  • 0 ≤ n5 ≤ 10
  • 0 ≤ n6 ≤ 10
  • 0 ≤ x ≤ 104

とする。

また、データ数が増加するに伴い計算時間がどう変化するか計測して確認しなさい。

【ヒント】 「貪欲法」を使う典型的な問題です。

例5-1

x =  1672
9

例5-2

x =  5549
24

例5-3

x =  3067
11

例5-4

x =  8802
False

例5-5

x =  -124
False

参考:例の作り方

import random
x = random.randint(0, 10000)
6
14
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?