極めよプログラミング道!【実力判定:Aランク】その2
締め切りが 2017/12/31 10:00 AM なので,その 1 分後に投稿されるように予約
【問題】
1階は1部屋、2階は1部屋、3階は2部屋、4階は3部屋、5階は5部屋、6階は8部屋、7階は13部屋と、増えていく塔があります。
3階以降は、下の2つの階にある部屋数の合計となります。ただし、部屋数が16以上になった場合は、合計を16で割った余りとなります。
ある階数が示された場合、その階に何部屋あるのか答えてください。
提示される階数は、1から1000000000の範囲とします。
【入力】
標準入力から、複数行のデータが与えられます。1行のデータが、1セットの数字になります。
1セットの数字は、1つの階数の数字です。
【出力】
1行ずつ計算して、答えとなる数字を1行ごと標準出力に出力します。
【入出力サンプル】
Input
4
5
6
8
Output
3
5
8
5
==========================================
周期24とは,短すぎるだろ。列挙しちゃうぞ。
g = function(n) {
a = c(1, 1, 2, 3, 5, 8, 13, 5, 2, 7, 9, 0, 9, 9, 2, 11, 13, 8, 5, 13, 2, 15, 1, 0)
cat(sprintf("%i\n", a[(n-1)%%24+1]))
}
arg = scan(file("stdin", "r"))
junk = sapply(arg, g)
実力判定:Sランク
締め切りが 2017/12/31 10:00 AM なので,その 1 分後に投稿されるように予約
【問題】
0から9の整数を、縦横それぞれN個並べた四角形があります。
左上から右下に、右あるいは下へと移動しながら、数を足していきます。
複数ある経路のうち、最小合計値となる経路をたどった場合の、合計値を答えてください。
ただし、Nは、2≦N≦20 の範囲の整数とします。# 20 ではなく 1000 だ!
例
567
133
502
上記の場合の全経路と合計値。
route: 56732, sum: 23
route: 56332, sum: 19
route: 56302, sum: 16
route: 51332, sum: 14
route: 51302, sum: 11
route: 51502, sum: 13
上記の場合の、最小合計値となる経路の図示。
567
133
502
最小合計値は「11」。
【入力】
標準入力から、複数行のデータが与えられます。縦横同じ文字数で、1つの正方形が作られます。
【出力】
最小合計値となる経路をたどった場合の合計値を、標準出力に出力します。
【入出力サンプル】
Input
567
133
502
Output
11
================================
R では簡単に書けるが,時間制限に引っかかる
f = function(s) {
x = t(sapply(s, function(t) as.integer(unlist(strsplit(t, "")))))
n = nrow(x)
x[1:n, 1] = cumsum(x[1:n, 1])
x[1, 1:n] = cumsum(x[1, 1:n])
for (i in 2:n) {
for (j in 2:n) {
x[i, j] = x[i, j] + min(x[i-1, j], x[i, j-1])
}
}
x[n, n]
}
cat(f(readLines(file("stdin", "r"))))
Java で書き直して OK となる
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int i, m;
int n = 0;
int[][] x = new int[1000][1000];
Scanner cin = new Scanner(System.in);
String line;
while (cin.hasNextLine()) {
line = cin.nextLine();
if (line.length() == 0) {
break;
}
String[] ch = line.split("");
m = ch.length - 1;
for (i = 0; i < m; i++) {
x[n][i] = Integer.parseInt(ch[i + 1]);
}
n++;
}
System.out.println(f(x, n));
}
static int f(int[][] x, int n) {
int i, j;
for (i = 1; i < n; i++) {
x[i][0] += x[i - 1][0];
x[0][i] += x[0][i - 1];
}
for (i = 1; i < n; i++) {
for (j = 1; j < n; j++) {
x[i][j] += Math.min(x[i - 1][j], x[i][j - 1]);
}
}
return x[n - 1][n - 1];
}
}
実力判定:Aランク
締め切りが 2017/12/31 10:00 AM なので,その 1 分後に投稿されるように予約
【問題】
1から1,000,000までの整数の範囲で、連続する2値を合計します。
2値の合計が、整数Nの倍数になる組み合わせを、数えてください。
ただし、整数Nは、2≦N≦1,000 の範囲とします。
例
整数Nが11の場合、「5, 6(合計は11)」、「16,17(合計は33)」……という組み合わせが、整数Nの倍数になります。
また、連続する2値の最小は「1, 2(合計は3)」、最大は、「999999, 1000000(合計は1999999)」になります。
【入力】
標準入力から、複数行のデータが与えられます。1行のデータが、1つの整数Nになります。
【出力】
1行ずつ処理を行ない、その答えを1行ごと標準出力に出力します。
【入出力サンプル】
Input
307
456
545
165
Output
3257
0
1835
6061
=======================
1000行のテストデータがあるんだけど,その中に同じ値が複数個ある。
テストデータの準備としては,漫然としており,だらしない。
期待される結果と違うといわれたのであるが,テストデータがあまりにも多いので,どれが間違えているのか(あるいは,プログラムに不備があるのか)なかなかわからなかった。
結果としては,答えが 200000 となる場合に R では 2e+5 と出力されることがあるのが原因であった(options(scipen=100) とでもしておけばよいのだが)。
f = function(N) {
invisible(sapply(N, function(n) {
if (n %% 2 == 0) {
m = 0
} else {
m = (1999999 %/% n + 1) %/% 2
}
options(scipen=100)
cat(m, "\n", sep="")
}))
}
f(scan(file("stdin", "r")))
より簡単に書くとこうなる。
f = function(N) {
options(scipen=100)
cat((ifelse(N %% 2, 1999999, 0) %/% N + 1) %/% 2, sep="\n")
}
f(scan(file("stdin", "r")))
実力判定:Cランク
締め切りが 2017/12/31 10:00 AM なので,その 1 分後に投稿されるように予約
きっと,締め切りは,再来年,再々来年...と繰り延べられるのだろうけど
【問題】
「0123456789」の10枚のカードの内、4枚のカードが提示されます。
通常は、「最も数値が大きなカード」が勝利者のカードです。
4枚の中に0があれば、「0以外で最も小さなカード」が勝利者のカードです。
勝利者のカードの数値を割り出してください。
【入力】
標準入力から、複数行のデータが与えられます。1行のデータが、1セットのゲームになります。
1行のデータは、数字4文字の文字列になります。この1文字ずつが、1枚のカードになります。
【出力】
1行ずつ結果を判定して、その答えとなる数字を、1行ごと標準出力に出力します。
【入出力サンプル】
Input
1234
6745
0149
3705
Output
4
7
1
3
==============================================================
R
f = function(S) {
for (s in S) {
s = as.integer(unlist(strsplit(s, "")))
i = which(s == 0)
if (length(i) > 0) {
x = min(s[-i])
} else {
x = max(s)
}
cat(x, "\n", sep="")
}
}
f(readLines(file("stdin", "r")))
==============================================================
AWK
awk '{
split($0, x, "")
Min = 100
Max = -100
zero = 0
for (i = 1; 4 >= i; i++) {
if (x[i] == 0) {
zero = 1
}
else {
Min = Min < x[i] ? Min : x[i]
Max = Max > x[i] ? Max : x[i]
}
}
if (zero == 1) {
print Min
}
else {
print Max
}
}
'
==============================================================
Perl
use strict;
use warnings;
use utf8;
use List::Util qw/max min/; # min, max 関数を使うため
my ($line, $i, @char, $Min, $Max, $zero);
while (defined(my $line = )) {
# print $line;
@char = split(//, $line);
$Min = 10;
$Max = -10;
$zero = 0;
for ($i = 0; $i < 4; $i++) {
if ($char[$i] == 0){
$zero = 1;
}
else {
$Min = min($Min, $char[$i]);
$Max = max($Max, $char[$i]);
}
}
if ($zero) {
print $Min, "\n";
}
else {
print $Max, "\n";
}
}
==============================================================
VB.net
imports System
module Crank
sub Main()
dim line as String
dim m as Integer
dim Min, Max, ans as Integer
dim zero as Boolean
for i as integer = 1 to 100
line = Console.ReadLine() ' コンソールから入力
Min = 10
Max = -10
zero = False
for i as integer = 1 to 4
m = Integer.Parse(mid(line, i, 1)) ' 文字列を整数に変換
if (m = 0) then
zero = True
else
Min = Math.min(Min, m)
Max = Math.max(Max, m)
end if
next
if (zero) then
ans = Min
else
ans = Max
end if
Console.WriteLine(ans) ' コンソールに出力 改行しないなら Console.Write()
next
end sub
end module
実力判定:Bランク
締め切りが 2017/12/31 10:00 AM なので,その 1 分後に投稿されるように予約
きっと,締め切りは,再来年,再々来年...と繰り延べられるのだろうけど
【問題】
20桁の数字が提示されます。
一番左の桁を先頭として、右の桁へと順に見ていきます。
そして、隣り合った数が連続する数だった場合は、その双方を削除して先頭に戻ります。
最終的に、削除ができなくなった時点で数字を出力してください。
例
「95422357545868773174」→「95422357545868773174」→
「922357545868773174」→「922357545868773174」→
「9257545868773174」→「9257545868773174」→
「92575868773174」→「92575868773174」→
「925758673174」→「925758673174」→
「9257583174」(削除ができなくなったので、これが答え)
【入力】
標準入力から、複数行のデータが与えられます。1行のデータが、1つの20桁の数字になります。
【出力】
1行ずつ処理を行ない、その答えを1行ごと標準出力に出力します。
【入出力サンプル】
Input
95422357545868773174
24566191298259441958
34757881545564825469
86423251489513547814
Output
9257583174
26619259441958
75818269
8642511314
============================================
R による例解の一つ
f = function(S) {
invisible(sapply(S, function(s) {
x = as.integer(unlist(strsplit(s, "")))
repeat {
n = length(x)
found = FALSE
if (n == 1) break
for (i in 1:(n - 1)) {
if (abs(x[i] - x[i + 1]) == 1) {
found = TRUE
break
}
}
if (!found) break
x = x[-(i + 0:1)]
}
cat(paste(x, collapse = ""), "\n", sep = "")
}))
}
f(readLines(file("stdin", "r")))