今日も独りで立ち話

ポンコツ博士課程の院生が思ったことをそのまま書くブログ

MENU

知識0からプログラミングを始めた(AtCoder挑戦2週目)

 

先週にに引き続きAtCoderをやっていこうと思います

 

先週の様子はこちら

www.tachibanashi.com

 

勉強ペースが亀のように遅いので、APG4bが終わるのはいったいいつになるんだろうか…

少なくとも7月中旬には終わらせておきたいなあとは思っている

 

1週間毎日振れた感想としては、講義でCをやっていたときよりは楽しくできているし、(一応)理解も進んでいるな、ということ

パズルとかクイズみたいな感覚で問題を解けているので、意味も分からず書いていた講義の頃よりは充実感がある

 

1日目(1.11~)

1.11のコンテスト問題をB - Addition and Multiplicationから解いた

中でもB - Palindromic Numbersはなかなかてこずった

自分は以前学んだ%10を使って、桁を落としていく手法を使って、各桁の数を取得し、それらを比較することで、探索する方針にした

 #include<iostream>
using namespace std;
int main(){
int A, B;
cin >> A >> B;

int a, b, c, d, e, x = 0;
for(int i = A; i < B+1; i++){
a = i % 10;
b = (i/10) % 10;
c = (i/100) % 10;
d = (i/1000) % 10;
e = (i/10000) % 10;



if(a == e && b == d){

x += 1;

}
}
cout << x << endl;
}

 i をそのまま変数として計算させるのは、我ながらいいアイデアだったとは思うんだけど、桁を落としていくところができなかったので、またしてもパワープレイで対処することに… 

 

 今回、いいなあと思ったコードはこちらのもの

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

int main() {
int A,B,a,b,c,N,S;
cin >> A >> B;
S=0;
for(int i=1;i< 10; i++){
a =i;
for(int j=0;j<10; j++){
b = j;
for(int k=0;k<10;k++){
c = k;
N =10000*a+1000*b+100*c+10*b+1*a;
if(A<=N && N <=B){
S++;}
}
}
}
cout << S << endl;
}

自分は数字を1ずつ増やして判断して、を繰り返してカウントアップしていく感じだったけど

この人は数字を範囲内でがちゃがちゃっと回して、当てはまるものを探す感じのイメージのものだと思う

大枠から絞り込んでいくイメージは大事だなあと思った

 

 2日目

なし

3日目

なし

4日目、5日目

B - Shift only で一生躓いている

無限ループになってるっぽいんだけど、どこが間違っているかわからない

#include<iostream>
using namespace std;
int main(){
int N;
cin >> N;
int ans = 0;
int C = 0;

for(int i =0; i < N; i++){
int A;
cin >> A;
if(ans >= C){
ans = C;
C = 0;
}
else{
C = 0;
}


while(A > 1){

if(A % 2 == 0){
A /= 2;
C++;
}

}



}
cout << ans << endl;
}

 イメージとしてはデータ数が与えられて、その数を上限としてループを行う
入力データAを拾って、何回2で割れるかをCで記録し、それをansに入れ込む
2回目以降は同じ作業を行って、ansとCを比較し小さいほうの数を採用し、Cには0を入れて初期化
・・・というつもりだったのだけど、無限ループしているようなので、それ以前の問題になっており、どこが原因で無限ループしているのかわからない
無限ループを自分で見つけるのも訓練だと思うので、しばらく先に進めなさそう、南無

 

 6日目(1.11~1.12(A-添え字))

#include<iostream>
using namespace std;
int main(){
int N;
cin >> N;
int ans = 0;
int C = 0;

for(int i =0; i < N; i++){
int A;
cin >> A;



while(A % 2 == 0){

A /= 2;

C++;




}
if(i == 0){
ans = C;
C = 0;
}
else{
if(ans >= C && C != 0){
ans = C;
C = 0;
}
else{
C = 0;

}

}

}
cout << ans << endl;
}

こう書き直したら、なぜかうまくいった

変更点はiで処理の場合分けをしたこと

最初はansにそのままCを入れて、ループ2回目から比較をするようにした

Cはその都度リセットする方針もうまくいっていた

while(A > 1){

if(A % 2 == 0){
A /= 2;
C++;
}

}

状況証拠的に、この部分の記述が間違っていてエラーを吐いていたっぽい

i, A, C, ansを毎回出力しながらループをさせていたんだけど、偶数のときはうまく動いて、素因数に奇数を含むときにエラーコード9が出ていたので、奇数の場合の場合分けみたいなのが間違っていたんだと思う

計算自体はやってはいるけど、時間がかかりすぎている、という感じっぽく見えたから、無限ループとはまた違ったかも

Aはint型だから、A=10とかだと、A = 2.5→2, A = 1となってwhileの条件に当てはまらない状態が出てしまってエラーが出てたのかなと思った

自分の意図としては、2で割って1余ったら終わりで、その下限が1という意図で書いてたんだけど、この辺の認識があいまいだったかなという感じ

最初の書き方をするなら、Aの偶奇で場合分けをしないといけないけど、それをやるくらいなら、条件をうまく書き換えるほうが早いな、みたいな反省

 

EX12足したり引いたりで感心したコード

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

int main() {
string S;
cin >> S;
int a = 1;

for(int i = 0; i < S.size()-1; i=i+2) {
if(S.at(i+1) == '+'){
a++;
}
else if(S.at(i+1) == '-') {
a--;
}
}
cout << a << endl;

 

自分はi番目の文字が+or-で一致するか判定して、個数を数えて、その差を取って1に足すという計算を取っていたけど、 iを2つずつ飛ばすほうが確かにそれがスマートかも

 

A - AtCoder *** Contestなんだけど

getline(cin, x)で行を取得して、その行の何文字目を表示ってどうしたらいいんだろう

と書いて色々、修正してたら数を数え間違ってた

AtCoderの後ろにスペースが入ってるのを忘れてて、x.(7)でなんでいけないんだ…って悩んでたけど、x.at(8)で普通にできたわ