horoyoisawaのゴミ箱

いろいろ書きます

【Java】入力を受け取るときに間違えたやつ。

f:id:horoyoisawa:20201202125359p:plain
以下のようなコードを書いたとする。

import java.util.Scanner;

public class Solution {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int i = scan.nextInt();
        double d = scan.nextDouble();
        String s = scan.nextLine();
        scan.close();

        System.out.println("String: " + s);
        System.out.println("Double: " + d);
        System.out.println("Int: " + i);
    }
}

入力例は以下。
1
3.14
My name is horoyoisawa.

結果は以下。

String:
Double: 3.14
Int: 1

sの中身が空になる。

結構よくあるやつだ。だから一行加えてみる。

String ss = scan.nextLine(); // 追加
String s = scan.nextLine();

こうすると、

String: My name is horoyoisawa.
Double: 3.14
Int: 1

となり、望んだ結果が得られる。

見ればわかるように、改行を考慮していなかったことで生まれた間違いだ。

今後気をつけたい。

【Java】if文の驚き

f:id:horoyoisawa:20201202125359p:plain
Javaをなぜか書き始めた。

もちろん何も知らないので、if文やfor文から入るのだが、そこでC++では通じるがJavaでは通用しない書き方を見つけたので備忘録用に書き留めておく。(おそらくめちゃくちゃあるある)

// 偶数の場合にeven、奇数の場合にはoddを出力したい。
int n;
if(n % 2) System.out.println("odd");
else System.out.println("even");

これだとincompatible typeとなる。
required: boolean
fount: int

Javaではこのような適当な書き方は許してくれないらしい。

以下修正。

// 修正
int n;
if(n % 2 == 1) System.out.println("odd");
else System.out.println("even");

bashのexprについての疑問(追記予定)


bashで出力する方法の一番有名なものはechoだが、出力する前に計算を行いその結果を出力したい場合にはexprが使える。

read a
read b

# echoを使う場合
echo $(($a + $b))

# exprを使う場合
expr $a + $b

しかし、一部の環境ではexprがコンパイルエラーになった。なぜだろう。

気をつけるならexprではなくechoが安心だ。

AtCoder Beginner Contest 006 D - トランプ挿入ソート 誤答コード

問題

atcoder.jp

コード

#include <bits/stdc++.h>
using namespace std;

int main() {
  int n;
  int ans = 0;
  cin >> n;
  vector<int> c(n);
  set<int> s;
  for(int i=0;i<n;i++) cin >> c[i];
  for(int i=0;i<n;i++) {
    if(i == 0) s.emplace(c[i]);
    else {
      if(*s.rbegin() > c[i]) ans++;
      s.emplace(c[i]);
    }
  }
  cout << ans << endl;
}

素朴すぎたか。

AtCoder Beginner Contest 100 D - Patisserie ABC 誤答コード

問題

atcoder.jp

誤答コード

#include <bits/stdc++.h>
#define chmax(x, y) x = max(x, y);
using namespace std;
using P = pair<int, int>;
bool c1 (vector<long long> &a, vector<long long> &b) {
  return a[0] > b[0];
}
bool c2 (vector<long long> &a, vector<long long> &b) {
  return a[0] < b[0];
}
bool c3 (vector<long long> &a, vector<long long> &b) {
  return a[1] > b[0];
}
bool c4 (vector<long long> &a, vector<long long> &b) {
  return a[1] < b[1];
}
bool c5 (vector<long long> &a, vector<long long> &b) {
  return a[2] > b[2];
}
bool c6 (vector<long long> &a, vector<long long> &b) {
  return a[2] < b[2];
}
int main() {
  int n, m;
  cin >> n >> m;
  vector<vector<long long>> in(n, vector<long long>(3)), v1, v2, v3, v4, v5, v6;
  for(int i=0;i<n;i++) for(int j=0;j<3;j++) cin >> in[i][j];
  v1.assign(in.begin(), in.end());
  v2.assign(in.begin(), in.end());
  v3.assign(in.begin(), in.end());
  v4.assign(in.begin(), in.end());
  v5.assign(in.begin(), in.end());
  v6.assign(in.begin(), in.end());
  sort(v1.begin(), v1.end(), c1);
  sort(v2.begin(), v2.end(), c2);
  sort(v3.begin(), v3.end(), c3);
  sort(v4.begin(), v4.end(), c4);
  sort(v5.begin(), v5.end(), c5);
  sort(v6.begin(), v6.end(), c6);
  vector<vector<vector<long long>> *> vec(6);
  vec[0] = &v1;
  vec[1] = &v2;
  vec[2] = &v3;
  vec[3] = &v4;
  vec[4] = &v5;
  vec[5] = &v6;
  vector<vector<long long>> ans(6, vector<long long>(3));
  for(int i=0;i<m;i++) {
    for(int j=0;j<6;j++) {
      for(int k=0;k<3;k++) {
        ans[j][k] += (*vec[j])[i][k];
      }
    }
  }
  long long result = -1;
  for(int i=0;i<6;i++) {
    chmax(result, abs(ans[i][0]) + abs(ans[i][1]) + abs(ans[i][2]));
  }
  cout << result << endl;
  return 0;
}

提出結果

f:id:horoyoisawa:20200412091024p:plain

Runtime Errorが多い

どっかでオーバーフローしているか、範囲外アクセスしているか。

ローカルで動かしてみて結果が正しいが、ジャッジにはRE(Runtime Error)と判断された時

皆さんも一度は経験があるのではないか。ローカルでは動くけど、提出してみてエラーになる問題。

今回対象にしている問題はこちら。

atcoder.jp

コードを提出した結果とそのスクショはこちら。

atcoder.jp

f:id:horoyoisawa:20200406023429p:plain

提出結果

WAではなくREになっているのは、コードとして間違っている部分があることが多い。それを今回は発見していく。

提出コード

#include <bits/stdc++.h>
using namespace std;
int main() {
  int n, k, c;
  cin >> n >> k >> c;
  string s;
  cin >> s;
  vector<int> can;
  vector<int> ans;
  for(int i=0;i<n;i++) {
    if(s[i] == 'o') can.emplace_back(i);
  }
  vector<int> days(can.size()); 
  for(int i=n-1;i>=0;i--) {
    auto it = upper_bound(can.begin(), can.end(), can[i]+c);
    if(it == can.end()) days[i] = 1;
    else {
      int j = distance(can.begin(), it);
      days[i] = days[j] + 1;
    }
  }
  if(days.front() > k) {
    cout << endl;
    return 0;
  }
  int lim = -1;;
  for(int i=0;i<days.size();i++) {
    if(i == 0) {
      if(days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
    else if(i == days.size()-1) {
      if(can[i-1] <= lim || days[i] != days[i-1]) {
        ans.emplace_back(can[i]+1);
      }
    }
    else if(can[i] <= lim) continue;
    else if(can[i-1] <= lim) {
      if(days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
    else {
      if(days[i] != days[i-1] && days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
  }
  if(!ans.size()) cout << endl;
  else for(auto& el : ans) cout << el << endl;
  return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
  int n, k, c;
  cin >> n >> k >> c;
  string s;
  cin >> s;
  vector<int> can;
  vector<int> ans;
  for(int i=0;i<n;i++) {
    if(s[i] == 'o') can.emplace_back(i);
  }
  vector<int> days(can.size()); 
  for(int i=n-1;i>=0;i--) {
    auto it = upper_bound(can.begin(), can.end(), can[i]+c);
    if(it == can.end()) days[i] = 1;
    else {
      int j = distance(can.begin(), it);
      days[i] = days[j] + 1;
    }
  }
  if(days.front() > k) {
    cout << endl;
    return 0;
  }
  int lim = -1;;
  for(int i=0;i<days.size();i++) {
    if(i == 0) {
      if(days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
    else if(i == days.size()-1) {
      if(can[i-1] <= lim || days[i] != days[i-1]) {
        ans.emplace_back(can[i]+1);
      }
    }
    else if(can[i] <= lim) continue;
    else if(can[i-1] <= lim) {
      if(days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
    else {
      if(days[i] != days[i-1] && days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
  }
  if(!ans.size()) cout << endl;
  else for(auto& el : ans) cout << el << endl;
  return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
  int n, k, c;
  cin >> n >> k >> c;
  string s;
  cin >> s;
  vector<int> can;
  vector<int> ans;
  for(int i=0;i<n;i++) {
    if(s[i] == 'o') can.emplace_back(i);
  }
  vector<int> days(can.size()); 
  for(int i=n-1;i>=0;i--) {
    auto it = upper_bound(can.begin(), can.end(), can[i]+c);
    if(it == can.end()) days[i] = 1;
    else {
      int j = distance(can.begin(), it);
      days[i] = days[j] + 1;
    }
  }
  if(days.front() > k) {
    cout << endl;
    return 0;
  }
  int lim = -1;;
  for(int i=0;i<days.size();i++) {
    if(i == 0) {
      if(days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
    else if(i == days.size()-1) {
      if(can[i-1] <= lim || days[i] != days[i-1]) {
        ans.emplace_back(can[i]+1);
      }
    }
    else if(can[i] <= lim) continue;
    else if(can[i-1] <= lim) {
      if(days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
    else {
      if(days[i] != days[i-1] && days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
  }
  if(!ans.size()) cout << endl;
  else for(auto& el : ans) cout << el << endl;
  return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
  int n, k, c;
  cin >> n >> k >> c;
  string s;
  cin >> s;
  vector<int> can;
  vector<int> ans;
  for(int i=0;i<n;i++) {
    if(s[i] == 'o') can.emplace_back(i);
  }
  vector<int> days(can.size()); 
  for(int i=n-1;i>=0;i--) {
    auto it = upper_bound(can.begin(), can.end(), can[i]+c);
    if(it == can.end()) days[i] = 1;
    else {
      int j = distance(can.begin(), it);
      days[i] = days[j] + 1;
    }
  }
  if(days.front() > k) {
    cout << endl;
    return 0;
  }
  int lim = -1;;
  for(int i=0;i<days.size();i++) {
    if(i == 0) {
      if(days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
    else if(i == days.size()-1) {
      if(can[i-1] <= lim || days[i] != days[i-1]) {
        ans.emplace_back(can[i]+1);
      }
    }
    else if(can[i] <= lim) continue;
    else if(can[i-1] <= lim) {
      if(days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
    else {
      if(days[i] != days[i-1] && days[i] != days[i+1]) {
        ans.emplace_back(can[i]+1);
        lim = can[i] + c;
      }
    }
  }
  if(!ans.size()) cout << endl;
  else for(auto& el : ans) cout << el << endl;
  return 0;
}

 疑うべきは配列の範囲外アクセスですよね!

となって発見できるのが、vector<int> daysの下のiの部分。nはもとも文字列sの長さであってdaysの長さではない。ここをdays.size()に直す。

そして提出した結果がこちら。

f:id:horoyoisawa:20200406024710p:plain

ACではないが、REではなくなった。

これで自分の解き方が間違っていることが大体わかった。あとはどこが間違っていたのかを考える段階。

これのどこが間違っていたのかに関しては別のノートでまとめようか。

では。