AOJ PG入門 #5

## はじめに
今回は初めて構造化プラグラムの問題を解いてみる。面白かったけど難しかった(-_-;)！！
## 問1.たてH cm よこ W cm の長方形を描くプログラムを作成して下さい。
1 cm × 1cm の長方形を '#'で表します。
- 入力は複数のデータセットから構成されています。各データセットの形式は H W
- H,Wがともに0のとき入力を終了
- 各データセットについて、H × W 個の '#' で描かれた長方形を出力して下さい。各データセットの後に、１つの空行を入れて下さい。

### PHP
```AOJ.php
<?php

while (true) {
    fscanf(STDIN, "%d %d", $h, $w);
    if ($h == 0 && $w == 0) break;

    for ($j = 0; $j < $h; $j++) {
        for ($i = 0; $i < $w; $i++) {
            echo "#";
        }
        echo "\n";  // 各行の後に改行
    }
    echo "\n";  // データセットの後に空行を入れる
}

?>
```
### 別解
```other.php
<?php
while (true) {
    list($H, $W) = array_map("intval", explode(' ', trim(fgets(STDIN))));
    if ($H == 0 && $W == 0) {
        break;
    }
    
    $line = str_repeat('#', $W) . "\n";
    $rectangle = str_repeat($line, $H);

    print($rectangle . "\n");
}
?>
```
- str_repeat→指定した回数分繰り返した文字列を返す。第一引数に繰り返す文字列、第二引数にその回数

### Java
```AOJ.java
import java.util.Scanner;
public class Main{
    public static void main(String[]args){
        Scanner sc = new Scanner(System.in);
        while(true){
            int h = sc.nextInt();
            int w = sc.nextInt();
            if(h==0&&w==0)break;
            for(int j=0;j<h;j++){
                for(int i=0;i<w;i++){
                    System.out.print("#");
                }
                System.out.println();
            }
            System.out.println();
        }
        sc.close();
    }
}
```
## 問2.フレームの描画
以下のような、たてH cm よこ W cm の枠を描くプログラムを作成して下さい。
```
##########
#........#
#........#
#........#
#........#
##########
```
- 入力は複数のデータセットから構成されています。各データセットの形式は H W
- H, W がともに 0 のとき、入力の終わりとします。
- 各データセットについて、たて H cm よこ W cm の枠を出力して下さい。各データセットの後に、１つの空行を入れて下さい。

### PHP
```AOJ.php
<?php
while(true){
    list($h,$w) = array_map("intval", explode(" ", trim(fgets(STDIN))));
    if($h == 0 && $w == 0) break;
    
    $line1 = str_repeat("#", $w) . "\n";
    $line2 = "#" . str_repeat(".", $w - 2) . "#\n";
    
    for($i = 0; $i < $h; $i++){
        if($i == 0 || $i == $h - 1){
            echo $line1;
        } else {
            echo $line2;
        }
    }
    echo "\n";
}
?>
```

### Java
```AOJ.java
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(true) {
            int h = sc.nextInt();
            int w = sc.nextInt();
            if(h == 0 && w == 0) break;
            
            // 上下の行を作成
            StringBuilder line1 = new StringBuilder();
            for(int j = 0; j < w; j++) {
                line1.append("#");
            }
            
            // 中間の行を作成
            StringBuilder line2 = new StringBuilder("#");
            for(int j = 0; j < w - 2; j++) {
                line2.append(".");
            }
            line2.append("#");
            
            for(int i = 0; i < h; i++) {
                if(i == 0 || i == h - 1) {
                    System.out.println(line1);
                } else {
                    System.out.println(line2);
                }
            }
            System.out.println();
        }
        sc.close();
    }
}
```
- StringクラスのrepeatメソッドはJava11以降。今回は代わりにStringBuilderオブジェクトのappendメソッドを利用して文字列を連結

### 別解
```other.java
import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner scan=new Scanner(System.in);
        while(true){
            int H=scan.nextInt();
            int W=scan.nextInt();
            if(H==0&&W==0)break;
            for(int i=0;i<H;i++){
                for(int j=0;j<W;j++){
                    if(i==0||i==H-1||j==0||j==W-1){
                        System.out.print('#');
                    }
                    else{
                        System.out.print('.');
                    }
                }
                System.out.println();
            }
            System.out.println();
        }
        scan.close();
    }
} 
```
## 問3.以下のような、たてH cm よこ W cm のチェック柄の長方形を描くプログラムを作成して下さい。
```
#.#.#.#.#.
.#.#.#.#.#
#.#.#.#.#.
.#.#.#.#.#
#.#.#.#.#.
.#.#.#.#.#
//上図は、たて 6 cm よこ 10 cm の長方形
```
- 入力は複数のデータセットから構成されています。各データセットの形式は H W
- H, W がともに 0 のとき、入力の終わり
- 各データセットについて、たて H cm よこ W cm の枠を出力して下さい。各データセットの後に、１つの空行を入れて下さい。
### PHP
```AOJ.php
<?php
while (true) {
    fscanf(STDIN, "%d %d", $h, $w);
    if ($h == 0 && $w == 0) break;

    //$line1 と $line2 を文字列として初期化し、ループの中で # や . を文字列として追加していく
    $line1 = "";
    $line2 = "";

    for ($i = 0; $i < $w; $i++) {
        if ($i % 2 == 0) {
            $line1 .= "#";
            $line2 .= ".";
        } else {
            $line1 .= ".";
            $line2 .= "#";
        }
    }

    for ($j = 0; $j < $h; $j++) {
        if ($j % 2 == 0) {
            echo $line1 . "\n";
        } else {
            echo $line2 . "\n";
        }
    }
    echo "\n"; // データセットの区切りとして空行を追加
}
?>
```
- PHPで配列のサイズを指定したいとき→array_fill() / 配列を初期化してループで要素を追加 
```arr.php
array_fill('開始インデックス, 要素数, 初期値');
```
### 別解
```other.php
<?php
while (true) {
    list($H, $W) = array_map("intval", explode(' ', trim(fgets(STDIN))));
    if ($H == 0 && $W == 0) {
        break;
    }
    
    $line1 = str_repeat('#.', (int) floor($W / 2)) . str_repeat('#', $W % 2) . "\n";
    $line2 = str_repeat('.#', (int) floor($W / 2)) . str_repeat('.', $W % 2) . "\n";
    $lines = $line1 . $line2;

    $board = str_repeat($lines, (int) floor($H / 2)) . str_repeat($line1, $H % 2);

    print($board . "\n");
}
?>
```
```other2.php
while (($input = trim(fgets(STDIN))) !== "0 0") {
    list($h, $w) = array_map("intval", explode(" ", $input));

    $s1 = substr(str_repeat("#.", intdiv($w+1, 2)), 0, $w);
    $s2 = substr(str_repeat(".#", intdiv($w+1, 2)), 0, $w);

    for ($i = 0; $i < $h; $i++) {
        print(($i % 2 === 0 ? $s1 : $s2) . "\n");
    }

    print("\n");
}

```

- subst関数→指定した文字列の一部を取得することができるPHPの組み込み関数
- intdiv($w+1, 2) は第一引数を第二引数で割った商を求める関数
```str.php
substr(対象文字列, 開始位置インデックス ,抽出する長さ)
```
- mb_substrも、指定した文字列の一部を取得する関数だが、mb_substrは、開始位置、文字数の指定に加えて、文字列の文字コードの指定を行うことができる。対象文字列が日本語の場合こっちを使うのがいい。
- substrがstr_repeatした文字列を切り取る関数と考えると、w が奇数の場合に切り取る部分が足りない→$w+1

### Java
```AOJ.java
import java.util.Scanner;
public class Main{
    public static void main(String[]args){
        Scanner sc = new Scanner(System.in);
        while(true){
            int h = sc.nextInt();
            int w = sc.nextInt();
            if(h==0&&w==0)break;
            
            for(int j = 0; j < h; j++){
                for(int i = 0; i < w; i++){
                    System.out.print((j+i)%2==0 ? "#" : ".");
                }
                System.out.println();
            }
            System.out.println();
        }
        sc.close();
    }
}
```
- チェック柄（碁盤の目のような模様）は、隣接する行と列で交互に色が変わるパターン

| 行 / 列 | 0 | 1 | 2 |
|--------|---|---|---|
| **0**  | # | . | # |
| **1**  | . | # | . |
| **2**  | # | . | # |