えらく時間がかかったPaiza「パスワード作成」

久しぶりの投稿になります。
あまりにも忙しく、ぜんぜんプログラミングの時間が作れませんでした。
とはいえ、Java入門編は修了し、現在はアルゴリズム入門の講座に入りました。
挿入ソートと選択ソートをなんとか実装できるようになったところです。

今回は、Paiza問題集からCクラス問題の「パスワード作成」を紹介します。
というのも、すぐできるかと思ったら結構時間がかかったので・・・

paiza.jp

ちょっとイヤだったのは、覚えない文字が与えられるのが一番最後というところでした。
理想は、配列のインデックスと覚える文字の位置を紐づけるというやり方だったのですが、覚えない文字が最後にあることでそれが(個人的には)難しくなりました。

なんとか書き上げたコードが以下

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int q =sc.nextInt();
        int[] passNum = new int[q];
        String[] passKey = new String[q];
        
        for (int i = 0; i < q; i++) {
            passNum[i] = sc.nextInt();
            passKey[i] = sc.next();
        }
        
        String c = sc.next();
        
        String[] pass = new String[n];
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < q; j++) {
                if (i == passNum[j] - 1) {
                    pass[i] = passKey[j];
                    break;
                } else {
                    pass[i] = c;
                }
            }
            System.out.print(pass[i]);
        }
    }
}

breakの位置をずっと間違っていて、覚えない値が何個も出力されて困ったりしましたが、なんとかこれでACでした。うーん、もっとうまいやり方があるんだろうな・・・

AtCoder Beginners Contest 340の感想

今週は仕事が忙しく、1週間お化粧もできないほどだったのですが、土曜の19時に完了して、「このままABC受けられるな」という発想が起き、1週間ほとんどプログラミングをやっていませんでしたが、挑戦してみました。

総評

ノーミスでAとBは解けました。
Cは考えたけどダメだったのと、Dからはさっぱりです。
数学の問題っぽいものは意味はわかるのに実装できないなあ。としょんぼり見つめていました。

順位は6838位。
ratingは今回で+24で30になりました。

A「Arithmetic Progression

https://atcoder.jp/contests/abc340/tasks/abc340_a

等差数列。数学の公式をそのまんま書いて終了。
Bのことを末項のnだと勘違いして一瞬止まりましたが・・・

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        int d = sc.nextInt();
        int n = (b - a) / d + 1;
        for (int i = 1; i <= n; i++) {
            System.out.print(a + (i - 1) * d);
            if (i != n) {
                System.out.print(" ");
            }
        }
        
    }
}

B「Append」

https://atcoder.jp/contests/abc340/tasks/abc340_b

解けたけどいまだによく分かってない問題です。(何がしたいんだ的な)

AC。これも割と簡潔に書けた気がする。

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        int q = sc.nextInt();
        ArrayList<Integer> a = new ArrayList<>();
        
        for (int i = 0; i < q; i++) {
            int key = sc.nextInt();
            if (key == 1) {
                a.add(sc.nextInt());
            } else {
                int y = sc.nextInt();
                System.out.println(a.get(a.size() - y));
            }
        }
    }
}


C「Divide and Divide」
https://atcoder.jp/contests/abc340/tasks/abc340_c

わかるのに解けなかったなあ。悔しいです。

途中まで書いたコードを載せておきます。

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        ArrayList<Integer> x = new ArrayList<>();
        x.add(n);
        
        int x1 = n;
        int x2 = n;
        int money = 0;
        
        for (int i = 0; i < 4; i++) {
            if (x.get(i) >= 2) {
                money += x1;
                x1 = x1 / 2; x2 = x1 - x1 / 2;
                x.add(x1);
                x.add(x2);
                System.out.println(x.get(i));
            }
        }
        
        System.out.print(money);
        
        
        /*
        int x = n
        int x1 = n / 2;
        System.out.print(x1);
        int x2 = n - x1;
        int money = 0;
        if (n >= 2) {
            money += n;
        }
        
        while (x >= 2) {
            int x = n / 2;
            int x2 = n - x;
            
            if (x >= 2) {
                money += 2 * x;
            } else if (x2 >= 2) {
                money += x2;
                x = x2;
            }
        }
        */
    }
}

ひとつわかったのは、ArrayListの要素すうが増えてもfor文のサイズで更新されるわけではないということ・・・
増えたら増えただけチェック数を増やしたかったのですが・・・

3回目のAtCoder Daily Training 3問完答

こんにちは。本日も水曜日のAtCoder Daily Trainingに参加しました。EASYです。

今回は解けそうな3問ミスなしでいけました。ひとまず安心。
この間のABCでめちゃめちゃだったので、少しですがchar型や配列を勉強して挑みました。
まだ「これってなんだっけ?」と立ち止まってしまうのですが、少しずつできているようなきがします。

1問目「Exponential or Quadratic」

A - Exponential or Quadratic


累乗の計算をするMath.powを知らなくて、大きな値だとパンクしてしまい時間がかかりました。(for文で書いてた)

Math.powを用いて引き算の正負を判定するという形にたどり着いてAC。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long n = sc.nextLong();
        
        if (Math.pow(2, n) - n * n > 0){
            System.out.print("Yes"); 
        } else {
            System.out.print("No");
        }
    }
}

2問目「Pawn on a Grid」

B - Pawn on a Grid

二重のfor文に辿り着くまでに随分時間がかかってしまいました。
よく考えれば、二次元配列も頭からすっぽ抜けていました・・・。が、なんとかAC

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int h = sc.nextInt();
        int w = sc.nextInt();
        
        int result = 0;
        
        for (int i = 0; i < h; i++) {
            String str[] = sc.next().split("");
            for (int j = 0; j < w; j++) {
                if (str[j].equals("#")) {
                    result += 1;
                }
            }
        }
        
        System.out.print(result);
    }
}

3問目「LOOKUP」

C - LOOKUP

これは配点的にはおそらくB問題かと思うのですが、前の日にPaizaの問題集で部分一致の問題を解いており、完全にラッキー問題でした。
3分くらいで、これが一番はやく解けました。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        String t = sc.next();
        
        int result = s.indexOf(t);
        
        if (result != -1) {
            System.out.print("Yes");
        } else {
            System.out.print("No");
        }
    }
}

4問目「TaK Code」

D - TaK Code

3問いけたので、とりあえず挑戦してみようと思ったのですが、むりでした・・・。

蓋を開けてみると、意外と愚直にやる問題のようです。3問解くのに40分かかってたら無理ですね・・・。


今週はABCに参加できないので、トレーニングだけでも参加できて良かったです。

ABC338でABCデビューからの撃沈

タイミングよく1/27(土)開催のAtCoder Beginner Contest 338に参加できたので、反省などを書きます。

結果

1問目を1ミスからAC。解けたのはこの問題のみでした。
char型を勉強しなきゃとは思いつつ手付かずで、解けそうな最初の2題が両方とも(おそらく)char型を用いる問題だったため、かなり苦戦しました。
順位は8789位。最下位と思ってたけど、苦戦した方は多かったようです。

ですが初参加でレーティングが0だったので、1問解けたからか +6 となりました。
現在レーティング 6

1問目「Capitalized?」

A - Capitalized?

char型だと分かっても、作るのが難しかった。

この手の問題は、いつもforで全チェックして出力する、という問題を解いていたからか、その結果を一言でっていうのが、慣れておらず・・・
最近知った数値に置き換えて判別するというやり方しか手数がなかったです。

しかし、何度やってもNoなのにYesが出ちゃってなんで〜〜〜と40分くらい格闘したりして、1度目の提出で半分くらいWA。

結局以下のコードでACになりました。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String S = sc.nextLine();    
        char[] Ssplit = new char[S.length()];
        
        for (int i = 0 ; i < S.length(); i++) {
            Ssplit[i] = S.charAt(i);
        }
    
        int m = 0;
        
        boolean result1 = Character.isUpperCase(Ssplit[0]);
        boolean result2;
        
        if (result1 == true) {
            for (int i = 1; i < Ssplit.length; i++) {
                result2 = Character.isLowerCase(Ssplit[i]);
                if (result2 == true) {
                    m = m + 0;
                } else {
                    m++;
                }
            }
            
            if (m == 0) {
                System.out.print("Yes");
            } else {
                System.out.print("No");
            }
            
        } else {
            System.out.print("No");
        }
    }
}

1問目はかかっても数分のつもりだったので、10分を過ぎてかなり焦って間違いも多発したし、支離滅裂な記述になってしまいました。残念。

解説にも、「この問題は人生最初のプログラミングとしてはやや大変でしょう」と書いており、やっぱ大変なんジャン・・

1文字目が大文字かどうかでまず場合分けするという点は良かったみたいです。

boolean ans = Character.isUpperCase(S.charAt(0));

for (int i = 1; i < S.length(); ++i) {
            ans &= Character.isLowerCase(S.charAt(i));
}

この書き方すごいですね。
見習えるんだろうか・・・
2文字目以降に1回でも小文字がきてしまったら、falseになってしまうので一生falseになってしまうという仕掛けでしょうか・・・

2問目「Frequency」

B - Frequency


これもダメでしたね〜。
char型が文字コードで管理できるのをマスターせねばなりません。

全アルファベット分の個数を入れられる配列を用意して、文字コードと結びつけて、文字数を格納して、最後にくらべるようです。

char、要復習ですね。



3問目以降は、今のままでは絶対できないので、今回はここまでにします。

2回目のAtCoder Daily Training EASY

プログラミング、続いています。
paizaスキルチェックのC問題はレートが低い順に1日1題程度解いています。
完答したり、しなかったり、ぼちぼちです。

現在のレートです。

この間も載せとけば良かったな。
現時点では、自分のレートより低い問題ばかり解いているので、なかなか上がらないですね。


さて、本日も水曜の16時枠でAtCoder Daily Training EASY部門に挑戦しました。
今回は、1時間まるまる使いました。時間が足りずに終わる、という感じで、前回より解ける問題が増えて嬉しかったです。

1問目「Spread」

A - Spread

標準入出力ができれば簡単です。
タイムは3:06でした。もっと早くできそうです。
上位の方は1分台ですね〜一瞬ですね;

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        String S = sc.nextLine();
        String[] Ssplit = S.split("");
        
        for (int i = 0; i < Ssplit.length; i++) {
            System.out.print(Ssplit[i]);
            if (i != Ssplit.length - 1) {
                System.out.print(" ");
            }
        }
        
    }
}

2問目「Adjacent Squares」

A - Adjacent Squares

いい感じにかけた!と思ったら、答えミスでやり直しになりました。
よく見てみると、(1, 1)のみなどのことを考慮していませんでした。

再提出バージョン

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        int h = sc.nextInt(); //たて
        int w = sc.nextInt(); //よこ
        int r = sc.nextInt();
        int c = sc.nextInt();
        
        if (h == 1 && w == 1) {
            System.out.print(0);
        } else if (h == 1 && w >= 1) {
            if (c == 1 || c == w) {
                System.out.print(1);
            } else {
                System.out.print(2);
            }
        } else if (h >= 1 && w == 1) {
            if (r == 1 || r == h) {
                System.out.print(1);
            } else {
                System.out.print(2);
            }
        } else if (r == 1 || r == h) {
            if (c == 1 || c == w) {
                System.out.print(2);
            } else {
                System.out.print(3);
            }
        } else if (c == 1 || c == w) {
            if (r == 1 || r == h) {
                System.out.print(2);
            } else {
                System.out.print(3);
            }
        } else {
            System.out.print(4);
        }
        
    }
}


解説を読みましたが、周りに解が存在するかどうか調べるという発想は、あったもののやり方を考える前に「大変かも!」と後回しにしてしまい、結局場合分で時間もかかったり、ミスをしたりと・・・
また後日やってみようと思います。

同値関係ってプログラミングで非常に大事ですね・・・・。

3問目「Booby Prize」

B - Booby Prize

ArrayListを2つ用意して、一方を昇順か降順に並び替えた上で、ブービー賞の人の点数を取得し、並び替えてないリストからその値のインデックスを取得する、という方法をとりました。

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); 
        ArrayList<Integer> a = new ArrayList<>();
        ArrayList<Integer> syozyun = new ArrayList<>();
        
        for (int i = 0; i < n; i++) {
            a.add(i, sc.nextInt());
            syozyun.add(a.get(i));
        }
        

        Collections.sort(syozyun);
        int num = syozyun.get(n - 2);
    
        
        System.out.print(a.indexOf(num) + 1);
    }
}

はじめは、

ArrayList <Integer> syozyun = a;

と書いていたのですが
なぜか、syozyunのリストを並び替えるとaまで並び替えが起こるという現象が起きて、????という感じで、結局この書き方で通りました。

まだArrayListを使うのが不安です。
講座復習必須。

4問目「Pentagon」

B - Pentagon

これは、途中まで書けたけど、回答が上手くいかずタイムアップになってしまいました。

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        String A = sc.nextLine(); 
        String B = sc.nextLine(); 
        
        String[] type1 = {"AB", "BA", "BC", "CB", "CD", "DC", "DE", "ED", "EA", "AE"};
        String[] type2 = {"AC", "CA", "AD", "DA", "BE", "EB", "BD", "DB", "CE", "EC"}; //10
        
        for (int i = 0; i < 10; i++) {
            
            if (A.equals(type1[i])) {
                if (B.equals(type1[i])){
                    System.out.print("Yes");
                    break;
                } else {
                    System.out.print("No");
                    break;
                }
            } else { //type2にAが当てはまる
                if (B.equals(type2[i])){    
                    System.out.print("Yes");
                    break;
                } else {
                    System.out.print("No");
                    break;
                }
            }
        }
    }
}

これだと、type1にあてはまるものしか正常に動作しません。
言語化できないですが、このコードがダメな理由はわかります。

解説は、短いか長いかで判断するようです。
2種類しかないので、type2までは要らなかったですね。



5問目はみる暇もありませんでした・・・
また時間のあるときに。

順位は13でした。前回より+1位ですが、解けた問題は増えたので、この間より満足してます。

大きな数値を3けたごとにカンマ区切りで出力する問題を読み間違える

前回の記事で、Cランクぜんぜん解けないと言ってましたが、その日にランクアップしました。
枠で囲む問題でした。
スキルチェックの問題は解法を書けないので割愛。


というわけで、今日はpaizaの問題集から、Cランクの問題です。

paiza.jp

この問題も、ずーっと解けなかったのですが、どこかで桁数が3の倍数かどうかで場合分けするという知見を得て、なるほど!と思い書き上げたのですが・・・・

import java.util.*;


public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String N = sc.nextLine();
        String[] num = N.split("");
        int ketasu = num.length;
        
        if (ketasu % 3 == 0) {
            int i = 3;
            System.out.print(num[0] + num[1] + num[2] + ",");
            while (i < ketasu - 3) {
                System.out.print(num[i] + num[i + 1] + num[i + 2] + ",");
                i = i + 3;
            }
            System.out.print(num[i] + num[i + 1] + num[i + 2]);
        } else if (ketasu % 3 == 2) {
            int i = 2;
            System.out.print(num[0] + num[1] +  ",");
            while (i < ketasu - 3) {
                System.out.print(num[i] + num[i + 1] + num[i + 2] + ",");
                i = i + 3;
            }
            System.out.print(num[i] + num[i + 1] + num[i + 2]);   
        } else if (ketasu % 3 == 1) {
            int i = 1;
            System.out.print(num[0] +  ",");
            while (i < ketasu - 3) {
                System.out.print(num[i] + num[i + 1] + num[i + 2] + ",");
                i = i + 3;
            }
            System.out.print(num[i] + num[i + 1] + num[i + 2]);   
        }
    }
}

いや、この問題、必ず3の倍数の桁数やんけ〜〜〜
一応解法を見てみたら、えらくシンプルで「???」となっていたのですが、問題文を読み返すと、3の倍数で割り切れる桁数の数字が入力されるとのこと・・・。
もうすっごい騙された気分。

でもこのコード十数分はかかったので、こちらで供養させていただきます。
たぶん他の問題で活きる・・・はず。

Javaプログラミング開始〜AtCoderコンテスト参加

コーディングの記録用に作成しました。

大学時代に少しJavaをやっていたのですが、2024年に入り、ちゃんと勉強したくなったので、paizaラーニングに登録&課金。

ただいま5日ほど経っているでしょうか。



Javaの新・入門編が半分ほど進み、制御とかで頭ごっちゃになってきたので、旧?入門編も並行して進めています。

スキルチェックのC問題がぜんぜん解けないので、まずは講座をクリアするのが目標です。



それとは別に、AtCoderも昔登録だけしていたので、できる問題ないかな〜とチェックしてみたら、AtCoder Daily Trainingという模擬テストみたいなものを週3くらいで行っていることを知り、EASY部門で挑戦してみることにしました。



こちらの問題は過去問だそうなので、解法の投稿が許されているようです。

このブログでは主にこの問題の記録について書いていこうと思っています。



さて、今回取り組んだのは2024/01/17(Wed)16:00〜のEASY部門です。

最初のA問題 Legendary Playersは難なく解けました。

A - Legendary Players


本当は別のクラスから引っ張ってくるみたいな書き方を想像してたんだけど、新・入門編の内容がぜんぜん入ってなくて、この方法しか書けなかったです。

import java.util.Scanner;
import java.util.LinkedHashMap;

public class Main{
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    LinkedHashMap<String, Integer> rating = new LinkedHashMap<>();
    
    rating.put("tourist", 3858);
    rating.put("ksun48", 3679);
    rating.put("Benq", 3658);
    rating.put("Um_nik", 3648);
    rating.put("apiad", 3638);
    rating.put("Stonefeang", 3630);
    rating.put("ecnerwala", 3613);
    rating.put("mnbvmar", 3555);
    rating.put("newbiedmy", 3516);
    rating.put("semiexp", 3481);
    
    String name = sc.nextLine();
    System.out.print(rating.get(name));
  }
}


プレビューだと色分けされてないんだけど、大丈夫なんだろうか・・・


それから、B問題は語尾が「er」か「ist」のいずれかの単語が入力され、どちらなのか判断して出力するという問題で、一見簡単なのですが、語尾をサーチする方法を知らなかったので、メソッドを調べました。

完全一致のequalsメソッドしか知らなかったけど、この機会にendsWithとstartsWithをしれて良かったです。使うぞ〜

B - Tires

import java.util.Scanner;

public class Main{
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    
    String S = sc.nextLine();
    
    if (S.endsWith("er")) {
      System.out.print("er");
    } else {
      System.out.print("ist");
    }
  }
}

で、これは実行チェックしたにも関わらず”ist”を”est”と間違えて記述してしまい、1度目はWAとなってしまいました。残念・・・




最後に、C・Dとにらめっこしたのですが、ぜんぜんでした・・・
Dの高橋くんの食べるものが嫌いなものの可能性を判定するという問題は、イメージを作って書いてみたけど、断念。

D - Takahashi's Failure

import java.util.Scanner;
import java.util.LinkedHashMap;

public class Main{
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int N = sc.nextInt();
    int K = sc.nextInt();
    
    LinkedHashMap<Integer, Integer> like = new LinkedHashMap<>();
    LinkedHashMap<Integer, Integer> dislike = new LinkedHashMap<>();
    
    for (int i = 0; i < N; i++) {
      like.put(i, sc.nextInt());
    }
    for (int i = 0; i < K; i++) {
      dislike.put(i, sc.nextInt());
    }
    
    int a = 0;
    int oishisa = like.get(a);
    if (like.get(a) <= like.get(a + 1)) {
      
    }
  }
}

おいしさの最大値を交換して、そのKeyを保持する、というふうにしたかったんですが、最大値が同じものの場合どうしたら良いんだ〜〜〜〜となって途中で終了しました。

最大値が同じものがあったら、それらのKeyを全て保持して・・・ってすると、収拾つかないきがしたし、おいしさの数値が全てバラバラだったらどうしていくんだろう?

何にせよ、今知識として持っているメソッドなどがあまりにも少ないので、知っていることを駆使してなんとか・・・と思ったのですが、これが限界でした。

記録のために、問題も載せたいけど、さすがにそれはダメかなあ?
今回はリンクにしておきます、、



C問題も、なんか頑張ればできそうな感じがするのですが、無限にフィールドがあるというのがわたしとしては厄介でした。

C - Number Box


早く入門編を終わらせて、アルゴリズムとか、他のメソッドとか仕入れて、また挑戦したいです。


今回は12位でした。半分くらいかな?
Bで間違えてなければ、もう少しいけたな。