以下の C による初歩の C プログラミング 100 本ノックを Julia で解いてみました。
基礎プロI 100本ノック 中級編
http://www.cc.kyoto-su.ac.jp/~mmina/bp1/hundredKnocksMiddle.html
各プログラムにおいて、特に指定が無い限りは入力値が指定された形式であるかどうかをチェックする必要はない(例えば整数型の値を入力させるところでアルファベットを入力された場合など)。
No. 40 even or odd
整数値を入力させ、その値が偶数ならばeven、奇数ならばoddと表示するプログラムを作成せよ。
print("input number:")
i = parse(Int, readline())
if iseven(i)
println("$i is even.")
else
println("$i is odd.")
end
input number:
stdin> 7
7 is odd.
以下のようにも。
print("input number:")
i = parse(Int, readline())
println(i, " is ", ["odd", "even"][iseven(i) + 1], ".")
input number:
stdin> 7
7 is odd.
No. 41 1桁の自然数?
整数値を入力させ、その値が一桁の自然数かそうでないか判定するプログラムを作成せよ。
print("input number:")
i = parse(Int, readline())
if 0 < i < 10
println("$i is a single figure.")
else
println("$i is not a single figure.")
end
input number:
stdin> 3
3 is a single figure.
以下のようにも。
print("input number:")
i = parse(Int, readline())
using Printf
@printf("%d %s a single figure.\n", i, 0 < i < 10 ? "is" : "is not")
input number:
stdin> 2
2 is a single figure.
No. 42 小さい順?
整数値を3つ入力させ、それらの値が小さい順(等しくてもよい)に並んでいるか判定し、小さい順に並んでいる場合はOK、そうなっていない場合はNGと表示するプログラムを作成せよ。
print("input number 1:")
i = parse(Int, readline())
print("input number 2:")
j = parse(Int, readline())
print("input number 3:")
k = parse(Int, readline())
if i <= j <= k
println("OK")
else
println("NG")
end
input number 1:
stdin> 4
input number 2:
stdin> 2
input number 3:
stdin> 3
NG
以下のようにも。
print("input number 1:")
i = parse(Int, readline())
print("input number 2:")
j = parse(Int, readline())
print("input number 3:")
k = parse(Int, readline())
println(["NG", "OK"][all(diff([i, j, k]) .>= 0) + 1])
input number 1:
stdin> 1
input number 2:
stdin> 3
input number 3:
stdin> 2
"NG"
No. 43 2次方程式の解の判別
2次方程式 ax^2 + bx + c = 0 (x^2はxの2乗の意味)の係数a, b, cを入力し、2次方程式の解が2つの実数解か、重解か、2つの虚数解かを判別するプログラムを作成せよ。
print("input a:")
a = parse(Int, readline())
print("input b:")
b = parse(Int, readline())
print("input c:")
c = parse(Int, readline())
d = b^2 - 4a*c
if d > 0
println("2つの実数解")
elseif d == 0
println("重解")
else
println("2つの虚数解")
end
input a:
stdin> 1
input b:
stdin> 4
input c:
stdin> 3
2つの実数解
以下のようにも。
print("input a:")
a = parse(Int, readline())
print("input b:")
b = parse(Int, readline())
print("input c:")
c = parse(Int, readline())
println(["2つの虚数解", "重解", "2つの実数解"][sign(b^2 - 4a*c) + 2])
input a:
stdin> 3
input b:
stdin> 2
input c:
stdin> -4
2つの実数解
No. 44 通貨換算
換算したい金額(円単位)と1ドル何円かを整数値で入力すると、入力した金額が何ドル何セントか計算して表示するプログラムを作成せよ。1セントは1/100ドルである。結果は整数値でよい(1セント未満の端数切り捨て)。
print("何円?")
円 = parse(Int, readline())
print("1ドルは何円?")
レート = parse(Int, readline())
(ドル, セント) = divrem(div(100円, レート), 100)
println(円,"円は",ドル,"ドル",セント,"セント")
何円?
stdin> 10000
1ドルは何円?
stdin> 120
10000円は83ドル33セント
divrem(div(100円, レート), 100) は以下のようなことをやっている。
print("何円?")
円 = parse(Int, readline())
print("1ドルは何円?")
レート = parse(Int, readline())
ドル = 円/レート
セント = 100(ドル - floor(ドル))
println(円,"円は",floor(Int, ドル),"ドル",floor(Int, セント),"セント")
何円?
stdin> 10000
1ドルは何円?
stdin> 120
10000円は83ドル33セント
No. 45 タクシー料金
初乗り料金が1700mまで610円、それ以降は313mごとに80円のタクシーがある。このタクシーに乗った距離をm単位で入力し、料金を計算するプログラムを作成せよ。
print("input number:")
距離 = parse(Int, readline())
if 距離 < 1700
println("金額 = 610")
else
println("金額 = $(610 + cld(距離 - 1700, 313)*80)")
end
input number:
stdin> 10000
金額 = 2770
ceil(a/b) と cld(a, b) の関係
print("input number:")
距離 = parse(Int, readline())
println("金額 = ", 610 + (距離 < 1700 ? 0 : cld(距離 - 1700, 313)*80))
input number:
stdin> 2014
金額 = 770
No. 46 入場料
神山美術館の入場料金は、一人600円であるが、5人以上のグループなら一人550円、20人以上の団体なら一人500円である。人数を入力し、入場料の合計を計算するプログラムを作成せよ。
print("input number:")
n = parse(Int, readline())
if n >= 20
println(500n)
elseif n >= 5
println(550n)
else
println(600n)
end
input number:
stdin> 22
11000
No. 47 値の入れ替え
異なる整数値を2つ入力し、それぞれ別の変数に格納する。そして、それらの変数の値を入れ替えた後、それぞれの変数の値を表示するプログラムを作成せよ。単に順序を変えて表示するだけではダメ。必ず変数の値を入れ替えること。下の実行例の場合、まず変数aに2、bに5が入力された状態から、aの値が5、bの値が2になるように入れ替える。
print("input a:")
a = parse(Int, readline())
print("input b:")
b = parse(Int, readline())
(a, b) = (b, a)
println("a = $a, b = $b")
input a:
stdin> 1
input b:
stdin> 2
a = 2, b = 1
Julia や Python では,一時変数を使用しないで値を入れ替えることができる。
No. 48 繰り返し計算
最初に2以上の整数値を入力し、次の規則で計算し、計算回数と計算結果を表示し、計算結果が1になるまで繰り返すプログラムを作成せよ。
規則:ある値が偶数ならその値を1/2にする。奇数ならその値を3倍して1を足す。
print("input number:")
n = parse(Int, readline())
count = 0
while n != 1
count += 1
if iseven(n)
n ÷= 2
else
n = (3n + 1)
end
println("$count: $n")
end
input number:
stdin> 3
1: 10
2: 5
3: 16
4: 8
5: 4
6: 2
7: 1
No. 49 九九
九九の表を、2重の繰り返しを使って表示するプログラムを作成せよ。2重の繰り返しを使わず単に表示するだけではダメ。値の間はタブ(\t)を使って間をあけること。
for i in 1:9
for j in 1:9
print("$(i*j)\t")
end
println()
end
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
「2重の繰り返しを使って」という条件を無視して以下のようにも書ける
Base.print_matrix(stdout, collect(1:9) .* collect(1:9)', "", "\t", "\n")
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
No. 50 foobar
1から100までの値を繰り返しで表示するが、3の倍数の時はfoo、5の倍数の時はbarと数字の代わりに表示するプログラムを作成せよ。なお、3と5の両方の倍数の時はfoobarと表示される。
for i in 1:100
if i % 15 == 0
println("foobar")
elseif i % 3 == 0
println("foo")
elseif i % 5 == 0
println("bar")
else
println(i)
end
end
1
2
foo
4
bar
foo
7
8
foo
bar
11
foo
13
14
foobar
:
bar
foo
97
98
foo
bar
No. 51 お支払い
指定した金額を100円玉と10円玉と1円玉だけで、できるだけ少ない枚数で支払いたい。金額を入力するとそれぞれの枚数を計算して表示するプログラムを作成せよ。
print("input money:")
money = parse(Int, readline())
(百円玉, res) = divrem(money, 100)
(十円玉, 一円玉) = divrem(res, 10)
using Printf
@printf("100円玉%g枚,10円玉%g枚,1玉%g枚\n", 百円玉, 十円玉, 一円玉)
input money:
stdin> 1234567
100円玉12345枚,10円玉6枚,1玉7枚
No. 52 閏年
西暦を入力したらその年が閏(うるう)年かどうかを判定するプログラムを作成せよ。なお、4で割り切れる年のうち、100で割り切れないか、400で割り切れる年は閏年である。
print("input year:")
year = parse(Int, readline())
using Dates
if isleapyear(Date(year))
println(year, "は閏年である")
else
println(year, "は閏年でない")
end
input year:
stdin> 2000
2000は閏年である
愚直に書く
print("input year:")
year = parse(Int, readline())
if year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
println(year, "は閏年である")
else
println(year, "は閏年でない")
end
input year:
stdin> 2000
2000は閏年である
No. 53 素因数分解
自然数の入力値を素因数分解して結果を表示するプログラムを作成せよ。
print("input number:")
n = parse(Int, readline())
using Primes
println(factor(Vector, n))
input number:
stdin> 840
[2, 2, 2, 3, 5, 7]
愚直に書く
print("input number:")
n = parse(Int, readline())
while n % 2 == 0
print(2, " ")
n ÷= 2
end
for i in 3:2:ceil(Int, sqrt(n))
if n != 1
while n % i == 0
print(i, " ")
n ÷= i
end
else
break
end
end
input number:
stdin> 840
2 2 2 3 5 7
No. 54 最大最小
まずデータの個数を入力させ、次にデータの個数だけ整数値を入力させる。この入力データの中で最大値と最小値を求め表示するプログラムを作成せよ。データの個数は100個までとする。なお、データの個数とデータはファイルからリダイレクトで入力させればよいので、入力のためのメッセージは不要である(実行例を参照すること)。
using Statistics
function minmax(filename)
txt = readlines(filename)
x = parse.(Int, txt[2:end]) # データは2行目以降
println("最小値 = $(minimum(x)), 最大値 = $(maximum(x))")
end
minmax("small.data")
minmax("middle.data")
minmax("large.data")
最小値 = 128, 最大値 = 962
最小値 = 20, 最大値 = 988
最小値 = 5, 最大値 = 996
No. 55 夢想花again
「とんで」を9回「まわって」を3回繰り返した後「まわる」と表示して改行する、を3回繰り返すプログラムを作成せよ。「とんで」「まわって」と3行文の繰り返しは必ず繰り返し構文を使うこと。
for i in 1:3
for j in 1:9
print("とんで")
end
for j in 1:3
print("まわって")
end
println("まわる")
end
とんでとんでとんでとんでとんでとんでとんでとんでとんでまわってまわってまわってまわる
とんでとんでとんでとんでとんでとんでとんでとんでとんでまわってまわってまわってまわる
とんでとんでとんでとんでとんでとんでとんでとんでとんでまわってまわってまわってまわる
No. 56 2進数変換
0〜65535の整数値を入力させ、入力値を16桁の2進数に変換して表示するプログラムを作成せよ。
print("input number:")
number = parse(Int, readline())
println(string(number, base=2, pad=16))
input number:
stdin> 10000
0010011100010000
愚直に書く
print("input number:")
number = parse(Int, readline())
bin = ""
for i in 1:16
(number, bit) = divrem(number, 2)
bin = string(bit) * bin # Julia では文字列の連結演算子は '*'
end
println(bin)
input number:
stdin> 10000
0010011100010000
No. 57 テスト集計
まず受験者数を入力させ、次に受験者数ごとに英語、数学、国語の点数をスペースで区切って入力させる(具体的な入力方法は下記のscanfの使い方の説明、および入力データの中身を見よ)。入力が終了したら、英語、数学、国語の平均点、および各受験生の合計点を計算して表示するプログラムを作成せよ。受験者数は100人までとする。なお、データの個数とデータはファイルからリダイレクトで入力させればよいので、入力のためのメッセージは不要である(実行例を参照すること)。
using Printf
using CSV, DataFramesMeta, Statistics
function exam(filename)
df = CSV.read(filename, DataFrame, skipto=2, header=["英語", "数学", "国語", ""])[!, 1:3]
# データフレーム用ではないデータフレームを読み込むための対応
# データが2行目以降 ==> skipto=2 を指定する
# ヘッダーがない ==> header=["英語", "数学", "国語", ""])
# データの各行の末尾に空白が入っている ==> [!, 1:3] で1~3列を取り出す(上記 header では 4 列分の名前を定義すること)
df = @transform df :合計点 = :英語 + :数学 + :国語
(英語, 数学, 国語) = mean.(eachcol(df))
@printf("平均点 英語:%g, 数学:%g, 国語:%g\n", 英語, 数学, 国語)
println("個人合計得点\n", df.合計点)
end
exam("examSmall.data")
exam("examMiddle.data")
exam("examLarge.data")
平均点 英語:46.3, 数学:51.3, 国語:55.9
個人合計得点
[141, 114, 107, 145, 201, 145, 201, 197, 96, 188]
平均点 英語:55.14, 数学:53.88, 国語:54.74
個人合計得点
[136, 64, 144, 101, 160, 261, 197, 164, 143, 116, 154, 185, 221, 142, 154, 179, 214, 141, 139, 80, 173, 191, 180, 144, 111, 213, 219, 88, 180, 193, 129, 198, 176, 207, 102, 109, 211, 169, 215, 231, 181, 157, 115, 106, 236, 114, 181, 132, 265, 167]
平均点 英語:52.87, 数学:51.32, 国語:51.12
個人合計得点
[151, 241, 145, 146, 156, 118, 128, 97, 184, 249, 203, 81, 191, 193, 58, 197, 77, 131, 165, 184, 135, 182, 164, 126, 94, 146, 260, 117, 170, 70, 139, 202, 216, 82, 117, 112, 101, 111, 107, 176, 106, 227, 253, 171, 243, 199, 192, 88, 177, 153, 234, 139, 103, 166, 148, 90, 141, 193, 127, 227, 195, 116, 98, 193, 141, 189, 206, 135, 135, 224, 204, 74, 212, 179, 185, 85, 246, 139, 177, 134, 162, 177, 182, 190, 126, 168, 78, 197, 172, 116, 81, 126, 95, 54, 162, 164, 289, 141, 107, 178]
行列として扱う
using Printf
function exam(filename)
f = open(filename, "r")
n = parse(Int, readline(f))
x = zeros(Int, n, 3)
for i in 1:n
x[i, :] = parse.(Float64, split(readline(f)))
end
(英語, 数学, 国語) = mean(x, dims=1)
@printf("平均点 英語:%g, 数学:%g, 国語:%g\n", 英語, 数学, 国語)
scores = sum(x, dims=2)
println("個人合計得点")
println(scores')
end
exam("examSmall.data")
exam("examMiddle.data")
exam("examLarge.data")
平均点 英語:46.3, 数学:51.3, 国語:55.9
個人合計得点
[141 114 107 145 201 145 201 197 96 188]
平均点 英語:55.14, 数学:53.88, 国語:54.74
個人合計得点
[136 64 144 101 160 261 197 164 143 116 154 185 221 142 154 179 214 141 139 80 173 191 180 144 111 213 219 88 180 193 129 198 176 207 102 109 211 169 215 231 181 157 115 106 236 114 181 132 265 167]
平均点 英語:52.87, 数学:51.32, 国語:51.12
個人合計得点
[151 241 145 146 156 118 128 97 184 249 203 81 191 193 58 197 77 131 165 184 135 182 164 126 94 146 260 117 170 70 139 202 216 82 117 112 101 111 107 176 106 227 253 171 243 199 192 88 177 153 234 139 103 166 148 90 141 193 127 227 195 116 98 193 141 189 206 135 135 224 204 74 212 179 185 85 246 139 177 134 162 177 182 190 126 168 78 197 172 116 81 126 95 54 162 164 289 141 107 178]
No. 58 棒グラフ
0以上の整数値を5つ入力させ、それぞれの値に対して、次の形式でグラフを描くプログラムを作成せよ。
形式:左端に値を表示し、適切に空白を空けて":"を書く(:で揃えるためにタブ\tを使うとよい)。その後ろに値の数だけ*を描くが、5個おきに空白を1つ入れる。具体例は下記の実行例を参照すること。
n = [(print("input data[$i]"); parse(Int, readline())) for i in 1:5]
for i in n
println(i, "\t:", replace("*" ^ i, "*****" => "***** "))
end
input data[1]
stdin> 4
input data[2]
stdin> 6
input data[3]
stdin> 5
input data[4]
stdin> 7
input data[5]
stdin> 23
4 :****
6 :***** *
5 :*****
7 :***** **
23 :***** ***** ***** ***** ***
No. 59 行列の和
3x3行列の和を求めて表示するプログラムを作成せよ。行列の値は2次元配列で表現し、繰り返しを使って計算すること。
3x3行列とは縦3つ、横3つの9つの要素(値)をひとまとめにして扱うものである。2つの3x3行列の和は次式のように、それぞれ同じ位置にある値を足したものとして計算できる。
function inputmatrix(size)
x = zeros(Int, size, size)
for i in 1:size
x[i, :] = parse.(Int, split(readline()))
end
return x
end
print("1つめの行列")
a = inputmatrix(3)
print("2つめの行列")
b = inputmatrix(3)
c = a .+ b
println(c)
println("和")
Base.print_matrix(stdout, c)
1つめの行列
stdin> 1 2 3
stdin> 4 5 6
stdin> 7 8 9
2つめの行列
stdin> 2 3 4
stdin> 5 6 7
stdin> 8 9 0
[3 5 7; 9 11 13; 15 17 9]
和
3 5 7
9 11 13
15 17 9