LoginSignup
6
5

More than 5 years have passed since last update.

Javaで解いてみた!! Paiza練習問題「長テーブルのうなぎ屋」 〜オブジェクト指向編〜

Posted at

はじめに

この記事は、プログラミング初心者が書いています。
間違っていること、もっとこうした方がいいよ!!等ございましたら、
コメントお願いします。

また、この問題はpaizaの練習問題になります。
ランクの上下には全く関係のないものですので、ご安心ください。

スクリーンショット 2018-10-29 22.17.03.png

非オブジェクト指向で書いたやつ

Javaで解いてみた!! Paiza練習問題「長テーブルのうなぎ屋」

こちらは手続き型(あってる?)で解いています。
この記事を投稿した際に、オブジェクト指向で書いたコードがあったため、
自分なりに消化させていただきました。

問題の具体的な内容などもこちらでご確認ください。

オブジェクト指向で考える

非オブジェクト指向で書いたコード

import java.util.*;

public class unagiya {

    public static void main(String[] args) {
        /*
         * 店の総席数、来店するグループ数をString型で取得しlineに格納
         * lineに格納したデータをsplitで分けてString配列のlineArrayに格納
         */
        Scanner scanner = new Scanner(System.in);
        String line = scanner.nextLine();
        String[] lineArray = line.split(" ");
        /*
         * lineArrayに格納したデータをキャストして各変数に格納
         * 
         * seatNum:座席の数
         * totalGuest:来店するグループの数
        */
        int seatNum = castString(lineArray[0]);
        int totalGuest = castString(lineArray[1]);

        /*
         * seats:座席数をhashMapで作成
         * Integerが席番号
         * Booleanが人の有無(trueなら座れる,)
         */
        Map<Integer,Boolean> seats = new HashMap<>();
        for(int i = 1; i <= seatNum; i++){
            seats.put(i,true);
        }
        /*
         *isSitCustomer:客が選んだ席に人がいるかいないか確認
         *いなければtrueを投げる
         *
         * choiceSeat:来た客が選ぶ基点となる席番号
         *menberNum:来た客の数
         */

        int choiceSeat = 0;
        int memberNum = 0;

        for(int i = 0; i < totalGuest; i++){
            //コンソールの入力値を受け取り、
            //memberNumとchoiceSeatに代入
            line = scanner.nextLine();
            lineArray = line.split(" ");

            memberNum = castString(lineArray[0]);
            choiceSeat = castString(lineArray[1]);

            //isSitGuestがtrueなら、客の選んだ席、人数の座席情報をfalseに書き換える
            if(isSitGuest(seats,choiceSeat,memberNum)){
                for(int j = 0,index = 1 ; j < memberNum; j++){
                    if(seats.size() < choiceSeat + j){
                        seats.put(index, false);
                        index++;
                    } else {
                        seats.put(choiceSeat + j,false);
                    }
                }
            }
        }

        //座席情報のfalseの数を調べてリザルトに代入
        int result = 0;

        for(int i = 1; i <= seats.size(); i++){
            if(seats.get(i).equals(false)){
                result++;
            }
        }
        System.out.println(result);
    }

    //String型の数値をint型にキャスト
    public static int castString(String strNum){
        int num = Integer.parseInt(strNum);
        return num;
    }

    /*
     * Map座席の情報、客が選んだ席、客の人数を受け取り、
     * 客が選んだ席から、客の人数分、falseがあるかチェック
     * 
     * 条件
     * 客の人数が席より多ければfalseを返す
     * 座席情報に一つでもfalseがあればfalseを返す
     */
    public static boolean isSitGuest(Map seats, int choiceSeat, int menberNum){
        if(menberNum > seats.size()){
            return false;    
        }

        boolean flag = true;

        for(int i = 0,index = 1; i < menberNum; i++){

            //index:座席情報の一番最初の1を指定
            //客の数が座席番号を超えたら1から数える時に使用

            if(seats.size() < choiceSeat + i){
                if(seats.get(index).equals(false)){
                    flag = false;
                    index++;
                } else {
                    index++;
                }
            } else if(seats.get(choiceSeat + i).equals(false)){
                flag = false;
            }

            }
        if(flag){
            return true;
        } else {
            return false;
        }
    }
}

だ、誰が書いたんだこのコード・・・

2週間ほど経って読み返してみたのですが、まあ見難い。
Mapで座席を作って色々やってますね・・・。
(途中で読むのをやめた)

この時の自分は「まあまあいいコード書けたぜw」なんて調子乗ってました。

しかし、流星のように現れたshiracamusさんの一言
「せっかくなのでオブジェクト指向しましょ」

その言葉と一緒に残していったコードがこちら
(shiracamusさんからコード掲載の許可をいただいております)

@shiracamusさんのコード

import java.util.*;

enum Seat { AVAILABLE, TAKEN };

class LongTable {
    private Seat seat[];

    LongTable(int seatNum) {
        seat = new Seat[seatNum];
        for (int i = 0; i < seatNum; i++) {
            seat[i] = Seat.AVAILABLE;
        }
    }

    boolean sit(int position, int num) {
        for (int i = position; i < position + num; i++) {
            if (seat[i % seat.length] != Seat.AVAILABLE) {
                return false;
            }
        }
        for (int i = position; i < position + num; i++) {
            seat[i % seat.length] = Seat.TAKEN;
        }
        return true;
    }
}

public class Unagiya {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] input = scanner.nextLine().split(" ");
        int seatNum = Integer.parseInt(input[0]);
        int groupNum = Integer.parseInt(input[1]);

        LongTable table = new LongTable(seatNum);

        int sitCount = 0;
        for (int i = 0; i < groupNum; i++){
            input = scanner.nextLine().split(" ");
            int memberNum = Integer.parseInt(input[0]);
            int seatNumber = Integer.parseInt(input[1]);

            if (table.sit(seatNumber, memberNum)) {
                sitCount += memberNum;
            }
        }

        System.out.println(sitCount);
    }
}

オブジェクト指向ってなんだっけ???

このコードを見た瞬間、体に電撃が流れました。

おそらく僕のコードをベースに書き直したのでしょう。

ならば僕はもっと時間を掛けて、
僕なりの「オブジェクト指向」で書いてみようと思います。

うなぎ屋の登場オブジェクト

僕はまず登場人物から考え始めます。

以前書いたフローチャートを参考に考えてみます。
スクリーンショット 2018-10-27 23.01.49.png

まずは
・長テーブル

enum Seat {AVAILABLE,UNAVAILABLE}

TAKENから
対象的なUNAVAILABLEに変更しました。

そしてテーブル。
テーブルはテーブルなので、メソッド(動作)はありません。そこにただ存在するだけです。


class LongTable {
    Seat[] seats;
    /**
     * テーブルを作成するコンストラクタ
     * 初期値はAVAILABLE
     * @param tableNum
     */
    LongTable(Integer tableNum) {
        this.seats = new Seat[tableNum];
        for (int i = 0; i < tableNum; i++) {
            seats[i] = Seat.AVAILABLE;
        }
    }
}

次に江戸っ子のお客さん。今回は少し気が早いとのことです。

席に人がいなかったら(isSit)座る(sitting)
席に人がいたら(isSit)帰る

class Guest {
    /**
     * 客が選んだ席に人がいなかったらtrueを投げるメソッド
     * @param guestNum
     * @param choiceNum
     * @param table
     * @return
     */
    public static Boolean isSit(Integer guestNum, Integer choiceNum, LongTable table) {
        Boolean seatConfirmation = true;
        for (int i = choiceNum; i < choiceNum + guestNum; i++) {
            if (table.seats[i % table.seats.length] == Seat.UNAVAILABLE) {
                seatConfirmation = false;
            }
        }
        return seatConfirmation;
    }
    /**
     * 客が座り、その席をUNAVAILABLEにするメソッド
     * @param guestNum
     * @param choiceNum
     * @param table
     */
    public static void sitting(Integer guestNum, Integer choiceNum, LongTable table) {
        for (int i = choiceNum; i < choiceNum + guestNum; i++) {
            table.seats[i % table.seats.length] = Seat.UNAVAILABLE; 
        }
    }
}

では、席に座っている人の数を数えるのは・・・
多分お店のスタッフさんになりますね。

class Staff {
    /**
     * 座っている人の数を数えるメソッド
     * @param table
     * @return count(SeatのUNAVAILABLEの数を数える)
     */
    public static Integer sitCount(LongTable table) {
        Integer count = 0;
        for (int i = 0; i < table.seats.length; i++) {
            if (table.seats[i] == Seat.UNAVAILABLE) {
                count++;
            }
        }
        return count;
    }
}

これで登場人物は揃いました。
あとはストーリーが進んでいくのを見守るだけです。

Mainメソッドの記述

ストーリーはmainメソッドに記述していきます。

public class Unagiya {
    public static void main(String[] args) throws Exception{
        //input:コンソールからの入力値を1行取得
        //inpuArray:1行の数値を分けて配列に格納
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        String[] inputArray = input.split(" ");

        //tableNum:うなぎ屋の座席の数
        //toDayGuest:本日ゲストが全部で何グループ来るか
        Integer tableNum = toCastString(inputArray[0]);
        Integer toDayGuest = toCastString(inputArray[1]);

        LongTable table = new LongTable(tableNum);

        //guestNum:1グループの人数
        //choiceNum:ゲストが選んだ席
        Integer guestNum = 0;
        Integer choiceNum = 0;
        for (int i = 0; i < toDayGuest; i++) {

            input = scanner.nextLine();
            inputArray = input.split(" ");

            guestNum = toCastString(inputArray[0]);
            choiceNum = toCastString(inputArray[1]);

            if (Guest.isSit(guestNum, choiceNum, table)) {
                Guest.sitting(guestNum, choiceNum, table);
            }
        }
        Integer count = Staff.sitCount(table);
        System.out.println(count);
    }
    /**
     * String型のアラビア数字をInteger型に変換するメソッド
     * @param strNum
     * @return num
     */
    public static Integer toCastString(String strNum) {
        Integer num = Integer.parseInt(strNum);
        return num;
    }

}

結果

スクリーンショット 2018-11-13 0.18.25.png

問題なく通りました。

参考

https://www.slideshare.net/masuda220/ss-14263541
こちらのスライドは非常に参考になるのですが、
縛りが非常に厳しいため、少し緩めにやっていますww

Paiza

意見、感想、改善点、僕の悪口、募集中です

僭越ながら2回目の記事投稿になりました。

Qiitaの暗黙の了解などおそらくガン無視して書いてます。

上記の件含め、読んでくださった方は、何か記録を残していただけるとありがたいです。
最後まで読んでくれた方、ありがとうございました。

6
5
18

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
5