12
4
paiza×Qiita記事投稿キャンペーン「プログラミング問題をやってみて書いたコードを投稿しよう!」

【paiza】最難関Sランクを開発未経験者がJavaで世界一丁寧に解いてみた!

Last updated at Posted at 2024-07-29

スクリーンショット 2024-07-30 6.39.48.png

皆様初めまして、システム開発未経験の趣味でアプリを作ろうと考えている素人浅はかエンジニア(自称)のirochiです!

今回取り上げさせていただくのは以下記事の 【paiza×Qiitaコラボキャンペーン】
Rank 「S」の問題です:v:!!

私iPhoneアプリ(簡単な家計簿)を作成したのと、大学4年間で浅い勉強をしただけのど素人ですが、今後のことも考えて腕試ししたかったので挑戦してみたという記事になってます!

前置きはここまでにして、以下早速問題をやっていきましょう!

【文字列収集 Java編】
https://paiza.jp/works/mondai/real_event/word_collection

とりあえず環境構築するぞーー!!!
って思ったら環境構築せずとも会員登録すればその場で実装するだけでした。。。
なんて便利なんでしょう。。。
(何も考えずにEclipseのインストールしちゃいました。。。:expressionless:

以下やっと問題始まります()

実際に解きます

問題文

あなたは文字列の愛好家で、文字列を収集することにとても熱心です。

文字列は市場で高値で取引されています。今、市場には N 個の文字列が出まわっており、文字列 S_i (1 ≦ i ≦ N) の価格は P_i です。 あなたは数ある文字列の中でも、とくに先頭がある特定の文字列で始まる文字列に興味があり、そのような文字列をすべて買い占めたいです。例え、同じ文字列が複数売っていたとしてもそのすべてを買います。

そこで、市場に出回っている N 個の文字列 S_i とそれぞれの価格 P_i (i ≦ i ≦ N)、また、M 個のクエリ文字列 Q_i (1 ≦ i ≦ M) が与えられるので、それぞれのクエリ Q_i に対し、市場に出回っている文字列の中で先頭が Q_i で始まる文字列すべてを買い占めるのに必要な金額を出力するプログラムを作成してください。

https://paiza.jp/works/mondai/real_event/word_collection より

まずは文章自体の意味が正座して考えないと難しいですね....
噛み砕いてみました⇩

市場には色々な文字列(例えば「apple」とか「banana」)があって、それぞれに値段がついています。そして、あなたは特定の文字列(例えば「a」や「ban」)で始まる文字列が好きすぎて、そのような文字列を全部買い占めたい!というわけです。(多分)

じゃあ、どうするか?
まず、市場にある全ての文字列とその値段をリストアップして、それから好きな文字列で始まるものを探して合計金額を計算します。

では、これをJavaで実装していきます。

どん!!!!!

import java.util.*;

public class Main {
    public static void main(String[] args) {
        // スキャナーを使って入力を読み込む
        Scanner scanner = new Scanner(System.in);
        
        // まず、NとMを読み込みます
        int N = scanner.nextInt(); // これは市場にある文字列の数
        int M = scanner.nextInt(); // これはクエリの数
        scanner.nextLine(); // 改行を消費して次の入力をスムーズにする
        
        // 文字列と価格を格納するリスト
        List<String> strings = new ArrayList<>();
        List<Integer> prices = new ArrayList<>();
        
        // 文字列とその価格をリストに格納します
        for (int i = 0; i < N; i++) {
            String str = scanner.next();
            int price = scanner.nextInt();
            strings.add(str);
            prices.add(price);
        }
        
        // ここからクエリに対して処理を行います
        for (int i = 0; i < M; i++) {
            String query = scanner.next(); // クエリ文字列を取得
            int totalCost = 0; // 合計金額を初期化
            
            // 文字列リストを確認して、クエリで始まるものを探す
            for (int j = 0; j < N; j++) {
                if (strings.get(j).startsWith(query)) { // startsWithでチェック
                    totalCost += prices.get(j); // 見つかったら値段を足す
                }
            }
            
            // 合計金額を出力
            System.out.println(totalCost);
        }
        
        // スキャナーを閉じる
        scanner.close();
    }
}

一つずつ分解していきます!!

スキャナーでの入力読み込み

まず、Javaで入力を読み取るには Scanner クラスを使います。これは「スキャナー」という名前の通り、標準入力からデータを読み取るのに使います。ここでは、最初に NM を読み取っていますが、これはそれぞれ「市場にある文字列の数」と「クエリの数」です。
標準入力とは値の入力を外部から受け取る方法で、入力された値によって処理を変化させます。

// スキャナーを使って入力を読み込む
Scanner scanner = new Scanner(System.in);
        
// まず、NとMを読み込みます
int N = scanner.nextInt(); // 市場にある文字列の数
int M = scanner.nextInt(); // クエリの数
Scanner scanner = new Scanner(System.in);

はJavaの言葉で表すとオブジェクトの生成をしていますが
よくわからん!って人はスキャナーの電源を入れるおまじないだと思っていただければ良いです!

その後、リストに文字列とその価格を格納していきます。ここでの List<String> strings は文字列のリストで、List<Integer> prices はその価格のリストです。

// 文字列と価格を格納するリスト
List<String> strings = new ArrayList<>();
List<Integer> prices = new ArrayList<>();

文字列と価格のリストを作成

次に、市場にある文字列とその価格を読み取ってリストに入れます。ループを使って N 回繰り返します。

for (int i = 0; i < N; i++) {
    String str = scanner.next(); // 文字列を読み込む
    int price = scanner.nextInt(); // その価格を読み込む
    strings.add(str); // 文字列リストに追加
    prices.add(price); // 価格リストに追加
}

クエリの処理

次に、クエリを処理していきます。クエリとは「どんな文字列で始まるものが欲しいか」という質問です。このクエリに対して、文字列リストの中から該当するものを探して、合計金額を計算します。

for (int i = 0; i < M; i++) {
    String query = scanner.next(); // クエリを読み込む
    int totalCost = 0; // 合計金額を初期化

    for (int j = 0; j < N; j++) {
        if (strings.get(j).startsWith(query)) { // startsWithでチェック
            totalCost += prices.get(j); // 見つかったら価格を足す
        }
    }
    
    // 合計金額を出力
    System.out.println(totalCost);
}

strings.get(j).startsWith(query) は、指定された文字列 query で始まるかどうかを確認するメソッドです。これを使って、strings リストの中にある文字列が、クエリで指定された文字列で始まるかどうかをチェックしています。
※後程解説あります!

最後に、各クエリに対して計算した合計金額を出力します。System.out.println(totalCost); で表示される数値が、そのクエリ文字列で始まる全ての文字列の価格の合計です。

提出してみた:writing_hand_tone1:

スクリーンショット 2024-07-30 6.39.48.png
スクリーンショット 2024-07-30 7.17.04.png

無事通過できて100点でした!!嬉しいい!!!!!
終わり

おまけ strings.get(j).startsWith(query)

以下具体的な解説です

例えば、リストに以下のような文字列があったとします

strings = ["apple", "banana", "apricot", "grape"]
strings.get(0) //には1つ目の要素"apple"
strings.get(1) //には2つ目の要素"banana"
strings.get(2) //には3つ目の要素"apricot"
strings.get(3) //には4つ目の要素"grape"

そして、startsWithメソッドに対してクエリとして "ap" が与えられた場合、次のように strings 配列の各要素に対してチェックを行います

strings.get(0).startsWith("ap")

これは "apple""ap" で始まるかどうかを確認し
結果は true になります(apple の最初の2文字は ap だから)。

strings.get(1).startsWith("ap")

これは "banana""ap" で始まるかどうかを確認します。
結果は false です(banana の最初の文字は b だから)。

strings.get(2).startsWith("ap")

これは "apricot""ap" で始まるかどうかを確認します。
結果は true です(apricot の最初の2文字は ap だから)。

strings.get(3).startsWith("ap")

これは "grape""ap" で始まるかどうかを確認します。
結果は false です(grape の最初の文字は g だから)。

このようにして、リスト内の文字列がクエリ文字列で始まるかどうかを startsWith メソッドで確認しているわけです。true ならばその文字列はクエリに一致するので、該当する価格を合計に加えて完了!というわけです。

最後に

ここわかりにくいよ ばかやろー!!
っていうのがあればぜひおっしゃってください!!!!
私の成長痛に付き合ってくださるということで大歓迎いたします!!

ここまで閲覧していただきありがとうございました!!

12
4
0

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
12
4