2022年10月30日日曜日

文字列の検索・操作、文字列についての条件判定、アスキーコード、正規表現(3)


ABC303-A

問題概要

2つの文字列が与えられる。二つは、oが0に、1がlに互いに入れ替わっているかもしれないほかは同じか。

解答

n=gets.to_i
s=gets.chomp
t=gets.chomp
n.times do |i|
    if !(s[i]==t[i] || (s[i]=="1" && t[i]=="l" || s[i]=="l" && t[i]=="1") || (s[i]=="0" && t[i]=="o" || s[i]=="o" && t[i]=="0"))
        puts "No"
        exit
    end
end
puts "Yes"
    

上が本番で提出したコード。Cで書いたのが以下。

int readint(char *s);
#include<stdio.h>
#include<stdlib.h>
#define N1 5
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
    int n=readint(s1);
    free(s1);
    char *s2=(char*)malloc(sizeof(char)*(n+2));
    if(s2==NULL){
        printf("memory allocation to s2 failed\n");
        exit(1);
    }
    char *ts2=fgets(s2,n+2,stdin);
    if(ts2==NULL){
        printf("fgets(s2) failed\n");
        exit(1);
    }
    char *s3=(char*)malloc(sizeof(char)*(n+2));
    if(s3==NULL){
        printf("memory allocation to s2 failed\n");
        exit(1);
    }
    char *ts3=fgets(s3,n+2,stdin);
    if(ts3==NULL){
        printf("fgets(s3) failed\n");
        exit(1);
    }
    int i=0;
    while(i<n){
        if (*(s2+i) != *(s3+i)){
            if(!((*(s2+i)==108 && *(s3+i)==49) || (*(s2+i)==49 && *(s3+i)==108) || (*(s2+i)==111 && *(s3+i)==48) || (*(s2+i)==48 && *(s3+i)==111))){
                printf("No\n");
                exit(0);
            }
        }
        i++;
    }
    printf("Yes\n");
    return 0;
}
int readint(char *s){
    int i=0,ret=0;
    while(*(s+i)>=48 && *(s+i)<=57){
        ret*=10;
        ret+=*(s+i)-48;
        i+=1;
    }
    return ret;
}
    

各文字を2倍に

ABC306-A

問題概要

与えられた文字列の各文字を2個ずつ連結した新しい文字列を出力せよ。

解答

n=gets.to_i
s=gets.chomp
ss=[]
n.times do |i|
    ss[2*i]=ss[2*i+1]=s[i]
end
puts ss.join("")
    

上が本番で提出したコード。Cで書いたのが以下。

int readint(char *s);
#include<stdio.h>
#include<stdlib.h>
#define N1 4
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
    int n=readint(s1);
    free(s1);
    char *s2=(char*)malloc(sizeof(char)*(n+2));
    if(s2==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts2=fgets(s2,n+2,stdin);
    if(ts2==NULL){
        printf("fgets(s2) failed\n");
        exit(1);
    }
//    printf("n=%d\n",n);
//    printf("s=%s\n",s2);
    for(int i=0;i<n;i++){
        printf("%c",*(s2+i));
        printf("%c",*(s2+i));
    }
    free(s2);
    printf("\n");
    return 0;
}
int readint(char *s){
    int i=0,ret=0;
    while(*(s+i)>=48 && *(s+i)<=57){
        ret*=10;
        ret+=*(s+i)-48;
        i+=1;
    }
    return ret;
}
    

二つの文字列の組み合わせで回文が作れるか

ABC307-B

問題概要

文字列の配列が与えられる。2つの文字列の組み合わせで回文を作ることができるか。

解答

        n=gets.to_i
        strs=[]
        n.times do |i|
            strs[i]=gets.chomp
        end
        n.times do |i|
            flag2=false
            n.times do |j|
                if i==j
                    next
                end
                flag1=true
                s=strs[i]+strs[j]
                sz=strs[i].size+strs[j].size
                (sz/2).times do |k|
                    if s[k]!=s[sz-1-k]
                        flag1=false
                        break
                    end
                end
                if flag1==true
                    puts "Yes"
                    exit
                end
            end
        end
        puts "No"
    

二重ループを回して全ての組み合わせを試している。

上が本番で提出したコード。Cで書いたのが以下。

int readint(char *s);
#include<stdio.h>
#include<stdlib.h>
#define N1 5
#define N3 50
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
    int n=readint(s1);
    free(s1);
    char *s2=(char*)malloc(sizeof(char)*n*(N3+1));
    if(s2==NULL){
        printf("memory allocation to s2 failed\n");
        exit(1);
    }
    for(int i=0;i<n;i++){
        char *s3=(char*)malloc(sizeof(char)*(N3+2));
        if(s3==NULL){
            printf("memory allocation to s3 failed\n");
            exit(1);
        }
        char *ts3=fgets(s3,N3+2,stdin);
        if(ts3==NULL){
            printf("fgets(s3(%d)) failed\n",i);
            exit(1);
        }
        int j=0;
        while(*(s3+j)>=97 && *(s3+j)<=122){
            *(s2+i*(N3+1)+j)=*(s3+j);
            j++;
        }
        *(s2+i*(N3+1)+j)=0;
        free(s3);
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i==j)continue;
            char *s4=(char*)malloc(sizeof(char)*(N3*2+1));
            if(s4==NULL){
                printf("memory allocation to s4 failed\n");
                exit(1);
            }
            int k=0;
            while(*(s2+i*(N3+1)+k)!=0){
                *(s4+k)=*(s2+i*(N3+1)+k);
                k++;
            }
            int l=0;
            while(*(s2+j*(N3+1)+l)!=0){
                *(s4+k)=*(s2+j*(N3+1)+l);
                k++; l++;
            }
            *(s4+k)=0;
            int flag=1;
//            printf("i=%d j=%d s4=%s",i,j,s4);
            for(int h=0;h<k/2;h++){
                if(*(s4+h)!=*(s4+k-1-h)){
                    flag=0;
                    break;
                }
            }
            if(flag==1){
                printf("Yes\n");
                exit(0);
            }
            free(s4);
        }
    }
    printf("No\n");
    free(s2);
    return 0;
}
int readint(char *s){
    int i=0,ret=0;
    while(*(s+i)>=48 && *(s+i)<=57){
        ret*=10;
        ret+=*(s+i)-48;
        i+=1;
    }
    return ret;
}
    

最初、読み込んだ文字列(s3)の終端の判定は、while(*(s3+j)!=0 && *(s3+j)!="\n")としていたのだが、そうするとなぜか改行文字が入ってしまうので、上記のコードのようにした。


ABC312-A

問題概要

標準入力から文字列が与えられる。その文字列は、問題文に与えられる文字列の一覧に含まれるか。

解答

s=gets.chomp
a=["ACE","BDF","CEG","DFA","EGB","FAC","GBD"]
a.each do |it|
    if it==s
        puts "Yes"
        exit
    end
end
puts "No"
    

上が本番で提出したコード。Cで書いたのが以下。

int scmp1(char* s, char* t, int n);
int readint(char *s);
#include<stdio.h>
#include<stdlib.h>
#define N1 5
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
    *(s1+3)=0;
//    printf("s=%s\n",s1);
    const char *strs[]={
        "ACE","BDF","CEG","DFA","EGB","FAC","GBD"
    };
    for(int i=0;i<7;i++){
        if(scmp1(*(strs+i),s1,3)==0){
            printf("Yes\n");
            exit(0);
        }
    }
    printf("No");
    free(s1);
    return 0;
}
int readint(char *s){
    int i=0,ret=0;
    while(*(s+i)>=48 && *(s+i)<=57){
        ret*=10;
        ret+=*(s+i)-48;
        i+=1;
    }
    return ret;
}
int scmp1(char* s, char* t, int n){
    int i=0;
    while(1){
        if (*(s+i)==0 && *(t+i)==0) return 0;
        else if (*(t+i)!=*(s+i)) return (*(s+i)-*(t+i));
        else i++;
        if(i>=n+1){
            printf("s=%s, t=%s, i=%d\n",s,t,i);
            printf("Comparing failed.\n");
        }
    }
}
    

特定の文字の削除

ABC315-A

問題概要

与えられた文字列から母音を取り除いて出力せよ。

解答

vowels=["a","e","i","o","u"]
s=gets.chomp.split("")
s.delete_if {|a| vowels.include?(a)}
puts s.join("")
    

上が本番で提出したコード。Cで書いたのが以下。

#include<stdio.h>
#include<stdlib.h>
#define N1 102
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
    int i=0,j=0;
    while(*(s1+i)!=0){
        if(*(s1+i)==97 || *(s1+i)==101 || *(s1+i)==105 || *(s1+i)==111 || *(s1+i)==117){
            //printf("%d: vowel\n",i);
            i++;
        }else{
            //printf("%d: consonant\n",i);
            *(s1+j)=*(s1+i); i++; j++;
        }
    }
    *(s1+j)=0;
    printf("%s\n",s1);
    free(s1);
}
    

(保留中)

ABC320-B

問題概要

与えられた文字列のうち、回文となっている最長の連続部分列の長さを求めよ。

解答

まず、以下は本番で提出して1個だけWAになったコード。本番中にはどうしても原因がわからなかった。

s=gets.chomp.split("")
n=s.size
max=0
(0...n).each do |i|
    (i...n).each do |j|
        t=0
        k=j-i+1
        k.times do |l|
            if s[i+l]!=s[j-l]
                break
            else
                t+=1
            end
        end
    #       puts "#{i} #{j} #{k} #{t}"
        max=[max,t].max
    end
end
puts max
    

testcase04.txtでWAになっているので、後でその内容を見たところ、
UYWZYYUZUYUUZUYUZZYYZUZZUYYZWUZUYZUYZWZUYZWYUZZZUZYZYYUYYY
となっており、正解は5。一方、上記コードでは結果が6になる。

この問題は、一旦お預け。


検索

ABC322-A

問題概要

与えられた文字列の中でABCが初めて連続な部分文字列として現れる位置を出力せよ。

解答

n=gets.to_i
s=gets.chomp.split("")
(0..(n-3)).each do |i|
    if s[i]=="A" && s[i+1]=="B" && s[i+2]=="C"
        puts i+1
        exit  
    end
end
puts -1
    

上が本番で提出したコード。Cで書いたのが以下。

int readint(char *s);
#include<stdio.h>
#include<stdlib.h>
#define N1 5
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
    int n=readint(s1);
    free(s1);
    char *s2=(char*)malloc(sizeof(char)*(n+2));
    if(s2==NULL){
        printf("memory allocation to s2 failed\n");
        exit(1);
    }
    char *ts2=fgets(s2,n+2,stdin);
    if(ts2==NULL){
        printf("fgets(s2) failed\n");
        exit(1);
    }
    int i=0;
    while(i<n-2){
        if(*(s2+i)==65 && *(s2+i+1)==66 && *(s2+i+2)==67){
            printf("%d\n",i+1);
            exit(0);
        }else{
            i++;
        }
    }
    printf("%d\n",-1);
    free(s2);
}
int readint(char *s){
    int i=0,ret=0;
    while(*(s+i)>=48 && *(s+i)<=57){
        ret*=10;
        ret+=*(s+i)-48;
        i+=1;
    }
    return ret;
}
    

前方一致・後方一致

ABC322-B

問題概要

2つの文字列 s, t が与えられる。sの文字数をnとして、sがtの先頭からn文字、末尾からn文字に、ともに一致するならば0、先頭からのみ一致するならば1、末尾からのみ一致するならば、2、どちらにも一致しなければ3 を出力せよ。

解答

n,m=gets.chomp.split(" ").map(&:to_i)
s=gets.chomp.split("")
t=gets.chomp.split("")
flag1=flag2=true
n.times do |i|
    if s[i]!=t[i]
        flag1=false
    end
end
n.times do |i|
    if s[i]!=t[m-n+i]
        flag2=false
    end
end
if flag1==true && flag2==true
    puts 0
elsif flag1==true && flag2==false
    puts 1
elsif flag1==false && flag2==true
    puts 2
elsif flag1==false && flag2==false
    puts 3
end    
    

上が本番で提出したコード。Cで書いたのが以下。

int readint(char *s);
#include<stdio.h>
#include<stdlib.h>
#define N1 9
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
    int n=readint(s1);
    int i=0;
    while(*(s1+i)>=48 && *(s1+i)<=57){
        i++;
    }
    i++;
    int m=readint(s1+i);
    free(s1);
    char* s2=(char*)malloc(sizeof(char)*(n+2));
    if(s2==NULL){
        printf("memory allocation to s2 failed\n");
        exit(1);
    }
    char* ts2=fgets(s2,n+2,stdin);
    if(ts2==NULL){
        printf("fgets(s2) failed\n");
        exit(1);
    }
    char *s3=(char*)malloc(sizeof(char)*(m+2));
    if(s3==NULL){
        printf("memory allocation to s3 failed\n");
        exit(1);
    }
    char *ts3=fgets(s3,m+2,stdin);
    if(ts3==NULL){
        printf("fgets(s3) failed\n");
        exit(1);
    }
//    printf("n=%d m=%d\n",n,m);
//    printf("%s\n",s2);
//    printf("%s\n",s3);
    int flag_pre=1,flag_post=1;
    for(i=0;i<n;i++){
        if(*(s2+i)!=*(s3+i)){
            flag_pre=0;
            break;
        }
    }
    for(i=0;i<n;i++){
        if(*(s2+i)!=*(s3+m-n+i)){
            flag_post=0;
            break;
        }
    }
    int ans=3;
    if (flag_pre==1 && flag_post==1)ans=0;
    else if (flag_pre==1)ans=1;
    else if (flag_post==1)ans=2;
    printf("%d\n",ans);
    return 0;
}
int readint(char *s){
    int i=0,ret=0;
    while(*(s+i)>=48 && *(s+i)<=57){
        ret*=10;
        ret+=*(s+i)-48;
        i+=1;
    }
    return ret;
}
    

ABC323-A

問題概要

0と1からなる長さ16の文字列Sが与えられる。2以上16以下のすべての偶数iについて Sのi文字目が0か。

解答

s=gets.chomp.split("")
(1..8).each do |i|
    if s[2*i-1]!="0"
        puts "No"
        exit
    end
end
puts "Yes"
    

上が本番で提出したコード。Cで書いたのが以下。

#include<stdio.h>
#include<stdlib.h>
#define N1 18
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
//    printf("%s",s1);
    int i=0;
    while(i<8){
        if(*(s1+2*i+1)!=48){
            printf("No\n");
            exit(0);
        }
        i++;
    }
    printf("Yes\n");
    return 0;
}
    

ABC325-A

問題概要

2つの文字列S,Tがスペース区切りで与えられる。S+(スペース)+"san"を出力せよ。

解答

sei,mei=gets.chomp.split(" ")
ans=sei+" san"
puts ans
    

上が本番で提出したコード。Cで書いたのが以下。

sei,mei=gets.chomp.split(" ")
ans=sei+" san"
puts ans
    

ABC327-A

問題概要

与えられた文字列の中にaとbが連続している(順序は不問)ところがあるか。

解答

n=gets.to_i
s=gets.chomp
(1...n).each do |i|
    if s[i]=="a" && s[i-1]=="b" || s[i]=="b" && s[i-1]=="a"
        puts "Yes"
        exit
    end
end
puts "No"
    

上が本番で提出したコード。Cで書いたのが以下。

int readint(char *s);
#include<stdio.h>
#include<stdlib.h>
#define N1 102
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
    int n=readint(s1);
    free(s1);
    char *s2=(char*)malloc(sizeof(char)*(n+2));
    if(s2==NULL){
        printf("memory allocation to s2 failed\n");
        exit(1);
    }
    char *ts2=fgets(s2,n+2,stdin);
    if(ts2==NULL){
        printf("fgets(s2) failed\n");
        exit(1);
    }
    int i=0;
    while(i<N1-1){
        if ((*(s2+i)==97 && *(s2+i+1)==98) || (*(s2+i)==98 && *(s2+i+1)==97)){
            printf("Yes\n");
            exit(0);
        }
        i++;
    }
    printf("No\n");
    return 0;
}
int readint(char *s){
    int i=0,ret=0;
    while(*(s+i)>=48 && *(s+i)<=57){
        ret*=10;
        ret+=*(s+i)-48;
        i+=1;
    }
    return ret;
}
    

ABC329-A

問題概要

与えられた文字列を一文字ずつ空白区切りにして出力せよ。

解答

s=gets.chomp.split("")
puts s.join(" ")
    

上が本番で提出したコード。Cで書いたのが以下。

#include<stdio.h>
#include<stdlib.h>
#define N1 102
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
//    printf("%s",s1);
    int i=0,length=0;
    while(i<N1-1 && *(s1+i)!=0){
        i++;
        length++;
    }
    i=0;
    while(i<length-1){
        printf("%c",*(s1+i));
        printf("%c",32);
        i++;
    }
    printf("%c",*(s1+i));
    printf("\n");
    return 0;
}
    

ABC339-A

問題概要

与えられた文字列の中には、少なくとも一つの . がある。最後の . より後の部分を切り出して出力せよ。

解答

s=gets.chomp
n=s.size
start=0
(n-1).downto(0).each do |i|
    if s[i]=="."
        start=i
        break
    end
    end
puts s.slice(start+1,n-start)
    

上が本番の提出コード。(この日は足の怪我で仕事をお休みしたため、久しぶりの本番。)

Cで書いたのが以下。

#include<stdio.h>
#include<stdlib.h>
#define N1 102
int main(void){
    char *s1=(char*)malloc(sizeof(char)*N1);
    if(s1==NULL){
        printf("memory allocation to s1 failed\n");
        exit(1);
    }
    char *ts1=fgets(s1,N1,stdin);
    if(ts1==NULL){
        printf("fgets(s1) failed\n");
        exit(1);
    }
//    printf("%s",s1);
    int i=0,length=0;
    while(i<N1-1 && *(s1+i)!=0){
        i++;
        length++;
    }
    i=length-1;
    int period;
    while(i>=0){
        if(*(s1+i)==46){
            period=i;
            break;
        }
        i--;
    }
    i++;
    for(;i<length;i++)
    printf("%c",*(s1+i));
    printf("\n");
    return 0;
}
    

0 件のコメント:

コメントを投稿