問1.2つの整数 a と b を読み込んで、以下の値を計算するプログラムを作成して下さい
- a ÷ b : d (整数)
- a ÷ b の余り : r (整数)
- a ÷ b : f (浮動小数点数)
- d, r, f を1つの空白で区切って1行に出力して下さい。fについては、0.00001以下の誤差があってもよいものとします。
PHP
<?php
fscanf(STDIN,"%d %d",$a,$b);
$d = intdiv($a,$b);
$r = $a%$b;
$f = $a/$b;
printf("%d %d %f\n",$d,$r,$f);
?>
- 整数除算のとき→intvalとintdivは同じ動作だが、intdivの方が明確に整数除算を意図しているため、可読性が向上
- a / b はデフォルトで浮動小数点数として計算される
Java
import java.util.Scanner;
public class Main{
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
int d = a/b;
int r = a%b;
double f = (double)a/b;
System.out.printf("%d %d %f",d,r,f);
sc.close();
}
}
問2.半径 r の円の面積と円周の長さを求めるプログラムを作成して下さい。
面積と円周の長さを1つの空白で区切って1行に出力して下さい。出力は浮動小数点数とし、0.00001 以下の誤差を含んでもよいものとします。
PHP
<?php
fscanf(STDIN,"%f",$r);
printf("%f %f\n",M_PI*$r*$r,2*M_PI*$r);
?>
- M_PIはPHPの定義済み定数。πの近似値を返す。
Java
import java.util.Scanner;
public class Main{
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
double r = sc.nextDouble();
System.out.printf("%f %f\n",r*r*Math.PI,2*r*Math.PI);
sc.close();
}
}
- 定義済み定数Math.PIは円周率を返す
問3.2つの整数 a, b と1つの演算子 op を読み込んで、a op b を計算するプログラムを作成して下さい。
ただし、演算子 op は、"+"(和)、"-"(差)、"*"(積)、"/"(商)、のみとし、割り算で割り切れない場合は、小数点以下を切り捨てたものを計算結果とします。
- 入力は複数のデータセットから構成されています。各データセットの形式は以下のとおりです:
a op b - op が '?' のとき 入力の終わりを示します。このケースの出力は行ってはいけません。
- 各データセットについて、計算結果を1行に出力して下さい。
PHP
<?php
while($input=fgets(STDIN)){
list($a,$op,$b) = explode(" ",trim($input));
$a = (int)$a;
$b = (int)$b;
if($op == "?")break;
switch($op){
case "+" : $ans = $a + $b;
break;
case "-" : $ans = $a - $b;
break;
case "/" : $ans = floor($a / $b);
break;
case "*" : $ans = $a * $b;
break;
}
echo "$ans\n";
}
?>
- 演算子は文字列扱い
- 小数点以下切り捨て→floor関数
今回入力が a op bのように空白を入れて入力しているので、例えば3 + 5 と入力を受け取れば
trimで文字列の前後の空白(および改行)を削除
→explodeで空白(スペース)を区切り文字として、文字列「3 + 5」を分割
→分割された要素のそれぞれをlist関数でそれぞれの変数に格納
としている。
しかし入力が 3+5のように空白のないものだった場合、explodeは使えないので正規表現で分割する。
例
$line = "3+5"; // スペースなし
$line = trim($line); // "3+5"
// 正規表現で演算子を分割
if (preg_match('/(\d+)([+\-*/])(\d+)/', $line, $matches)) {
$a = (int)$matches[1];
$op = $matches[2];
$b = (int)$matches[3];
// 演算の処理(switch文など)
switch ($op) {
case '+': $c = $a + $b; break;
case '-': $c = $a - $b; break;
case '*': $c = $a * $b; break;
case '/': $c = floor($a / $b); break;
}
echo $c . "\n";
}
- preg_match() は 正規表現にマッチした部分を $matches 配列に格納する関数。
- () で囲んだ部分(キャプチャグループ)は、それぞれ $matches[1], $matches[2], ... に格納される。キャプチャグループを使わないとマッチした全体のみ取得。
- 書式は
preg_match(パターン, 検索対象の文字列, マッチ結果を格納する配列);
成功すると preg_match() は 1 を返し、配列にその結果が入る。失敗すると 0 を返す。
- \d+=一個以上の数字(\d=数字、+=一回以上)
- []=どれかひとつ
例えば$line = "3+5" の場合、上記の$matches配列の中身は以下のようになる
$matches = [
0 => "3+5", // 全体のマッチ部分(入力全体)
1 => "3", // 1つ目の `(\d+)` にマッチ(最初の数値)
2 => "+", // `([+\-*/])` にマッチ(演算子)
3 => "5" // 2つ目の `(\d+)` にマッチ(次の数値)
];
Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true) {
String input = sc.nextLine();
String[] math = input.split(" ");
if (math[1].equals("?")) break; // "?" ならループ終了
int a = Integer.parseInt(math[0]);
int b = Integer.parseInt(math[2]);
int ans = 0;
switch (math[1]) {
case "+": ans = a + b; break;
case "-": ans = a - b; break;
case "*": ans = a * b; break;
case "/": ans = a / b; break;
}
System.out.printf("%d%n", ans);
}
sc.close();
}
}
- split() の引数は 正規表現 なので、 " "(ダブルクォートの空白)
- Javaでは文字列を比較する際は == ではなく equals() を使う。
- math[0] や math[2] は String 型 なので、そのまま計算できない。
→Integer.parseInt() でString型をint 型に変換
別解
import java.util.Scanner;
/* Name of the class has to be "Main" only if the class is public. */
class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){ //入力がある間はループ継続
long a = scanner.nextLong();
String str = scanner.next();
long b = scanner.nextLong();
switch(str) {
case "+":
System.out.println(a+b);
break;
case "-":
System.out.println(a-b);
break;
case "/":
System.out.println(a/b);
break;
case "*":
System.out.println(a*b);
break;
default:
break;
}
}
}
//
}
-
hasNext関数→次の入力があるかどうかを確認するメソッド。次のトークン (単語) があるなら true を返す。
入力が終わっていたら false を返す。next() を呼び出す前に使うとエラーを防げる -
Scanner クラスの next() は、スペースや改行で区切られた次の文字列を取得するメソッド。
-
nextInt() や nextLong() は、空白 (スペース, タブ) や改行を区切りとして、次の数値だけを取得する。
数値の後に空白 ( ) や改行 (\n) があると、そこで読み取りを終了し、次の入力を待つ。
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a, b;
while (true) {
a = sc.nextInt(); // 整数aを入力
String c = sc.next(); // 演算子をStringとして取得
b = sc.nextInt(); // 整数bを入力
if (c.equals("?")) break; // 演算子が「?」の場合、ループを終了
// 演算子に応じて計算
if (c.equals("+")) {
System.out.println(a + b);
} else if (c.equals("-")) {
System.out.println(a - b);
} else if (c.equals("*")) {
System.out.println(a * b);
} else if (c.equals("/")) {
System.out.println(a / b);
}
}
}
}
問4.n個の整数ai(i=1,2,...n)を入力し、それらの最小値、最大値、合計値を求めるプログラムを作成してください。
- 1行目に整数の数nが与えられます。2行目にn個の整数aiが空白区切りで与えられます。
- 最小値、最大値、合計値を空白区切りで1行に出力してください。
PHP
<?php
$n = intval(trim(fgets(STDIN)));
$a = array_map('intval',explode(" ",(trim(fgets(STDIN)))));
printf("%d %d %d\n",min($a),max($a),array_sum($a));
?>
- explodeで文字列の要素から成る配列→array_mapで全要素をintval適用で整数にして整数要素から成る配列にする。
Java
import java.util.Scanner;
public class Main{
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[]a = new int[n];
for(int i = 0;i<n;i++){
a[i] = sc.nextInt();
}
int mi = 1000000;
int ma = -1000000;
int sum = 0;
for(int j = 0;j<a.length;j++){
mi = Math.min(mi,a[j]);
ma = Math.max(ma,a[j]);
sum += a[j];
}
System.out.println(mi + " " + ma + " " + sum);
sc.close();
}
}
- sumの型→intにしたら大きな数の合計で整数オーバーフローエラー。注意!