大原本  問73

午前試験免除制度対応!基本情報技術者試験のeラーニング【独習ゼミ】
まきさん  
(No.1)
文字を圧縮するプログラムなのは問題文から分かりました。
ただこのi,j,k,nの意味が分からずプログラムがどうやって動いているのか不明です自分自身でトレースをやっても何が出来て何が出来ないか分からない状態です。こんなにやっているのに致命的だな・・・・あほなのか

  1 2 1 1 2 3 4 1 2 3 1
a{a,a,b,c,c,c,c,d,d,d,e}
  
b{a,a,b,c,4,d,3,e}


runlength(文字の配列:a,整数型)
整数型i,j,k,n
文字型の配列("1","2","3","4","5","6","7","8","9")

i←1(aの配列)
j←0(bの配列)
while(i<=m)  m=2とします
      1<=2
j←j+1
1  0
b[j]←a[i]
  1     1
  a     a
n←1
k←i+1
2  1

while(k<=m)and(a[k]=a[i])
      2  2
n←n+1
2  1
k←k+1
3  2
endwhile

if(n>=3)
j←j+1
2  1
b[j]←c[n]

elseif(n=2)
j←j+1
3  2
b[j]←a[i+1]
  2     1+1
endif
i←k
3  3
endwhile
2024.05.23 17:25
boyonboyonさん 
FE シルバーマイスター
(No.2)
この投稿は投稿者により削除されました。(2024.05.23 23:40)
2024.05.23 23:40
boyonboyonさん 
FE シルバーマイスター
(No.3)
「同じ文字が、3個以上続いたら、その文字と個数に置き換える」
というのが、目的ですね。2個までは、そのままです。
例えば、c,c,c,cは、c,4 に置き換えます。

>文字型の配列("1","2","3","4","5","6","7","8","9")
これは、配列 c ではありませんか?
あと、 m は、配列 a の要素数ではありませんか?

以上を前提として、プログラムを見てみます。

a[]={a,a,b,c,c,c,c,d,d,d,e}

runlength(文字の配列:a,整数型)
整数型i,j,k,n
文字型の配列 c[]={"1","2","3","4","5","6","7","8","9"}

i←1(aの配列)
j←0(bの配列)

/* 配列の添字は、1から始まりますね。
/* j←0(bの配列)  は、最初にj←j+1の処理があるので、・・・別の書き込みにもありましたね。

while(i<=m)    /*配列 a の末尾になるまで繰り返します。
    j←j+1
    b[j]←a[i]  /*配列のコピー
    n←1        /*1文字目の代入です。(1個目)
    k←i+1      /*配列 a の現在位置の次

    while(k<=m)and(a[k]=a[i])
    /*配列 a の要素がまだ残っていて、次の位置の要素が、同じ文字
        n←n+1  /*同じ文字の個数を1増やします
        k←k+1  /*配列 a の次の位置にフォーカスを移動する
    endwhile
    /*同じ文字が続かなくなったら終わりです。
    /* n は、同じ文字が何文字続いたかの個数
    /* k は、現在走査済みの a の位置の次・・・①

    if(n>=3)          /*3個以上続くとき
        j←j+1        /*個数を代入する b の位置
        b[j]←c[n]    /*個数を代入(9個以上の時は???)
    elseif(n=2)       /*2個の時
        j←j+1        /*個数を代入する b の位置
        b[j]←a[i+1]  /*個数に置き換えずにそのまま文字を代入
    endif

    i←k  /* ①より、次に走査する配列 a の位置
endwhile

これで

b[]={a,a,b,c,4,d,3,e}

になると思います。
2024.05.23 23:40
まきさん  
(No.4)
>boyonboyonさん
解説ありがとうございます。参考にさせていただきます。
2024.05.28 15:29
jjon-comさん 
FE ゴールドマイスター
(No.5)
> プログラムがどうやって動いているのか不明です
という状況だったのに

> 参考にさせていただきます。
で、あっさり終わろうとしているのに違和感を持ちました。

質問者は納得できたのでしょうか?
納得していないのなら納得するまで食い下がればいいのだと思います。
しょせん匿名掲示板なのですから恥は掻き捨てですし,
回答者も,自分が回答したいから書いている。嫌になったら回答しないだけですから。

私は,疑似言語のプログラムコードはいったん無視して,
+―+―+―+―+―+―+―+―+―+―+―+
|a|a|b|c|c|c|c|d|d|d|e|
+―+―+―+―+―+―+―+―+―+―+―+
という入力データが与えられたとき,どういう動きをして
+―+―+―+―+―+―+―+―+
|a|a|b|c|4|d|3|e|
+―+―+―+―+―+―+―+―+
というデータが出力されると質問者がイメージしているのか。
紙と鉛筆のレベルで質問者が説明できるかが要点だと考えます。
2024.05.28 16:51
まきさん  
(No.6)
>jjon-comさん
>"参考にさせていただきます。"
で、あっさり終わろうとしているのに違和感を持ちました。

いつも解説ありがとうございます。
自分でも考えてみて疑問点が出せるように考えさせてください。
ちょっと時間をください。

一つ疑問点があるんですが、
>*配列 a の次の位置にフォーカスを移動すると書いてありますが
while(k<=m)and(a[k]=a[i])の部分で、
kの動き方なのですがあまりわからないです

mはaの配列数なので11となる
     1 2 3 4 5 6 7 8 9 10 11
[a]  a a b c c c c d d  d  e


1回目
     1 2 3 4 5 6 7 8 9 10 11
[a]  a a b c c c c d d  d  e
    ↑
     k
     1 2 3 4 5 6 7 8 9 10 11
[b]  a
   
      k=1
2回目
     1 2 3 4 5 6 7 8 9 10 11
[a]  a a b c c c c d d  d  e
      ↑
       k
     1 2 3 4 5 6 7 8 9 10 11
[b]  a a
       k=2
3回目
     1 2 3 4 5 6 7 8 9 10 11
[a]  a a b c c c c d d  d  e
        ↑
         k
     1 2 3 4 5 6 7 8 9 10 11
[b]  a a b
      k=3

4回目
     1 2 3 4 5 6 7 8 9 10 11
[a]  a a b c c c c d d  d  e
          ↑
           k
     1 2 3 4 5 6 7 8 9 10 11
[b]  a a b c
      k=4

5回目
     1 2 3 4 5 6 7 8 9 10 11
[a]  a a b c c c c d d  d  e
            ↑
             k
     1 2 3 4 5 6 7 8 9 10 11
[b]  a a b c 
      k=5

という具合に動いていくイメージなのでしょうか?

また
i←k  /* ①より、次に走査する配列 a の位置
とありますが、 k←k+1 では不可なのでしょうか?
2024.05.28 19:14
jjon-comさん 
FE ゴールドマイスター
(No.7)
変数kの動きは次のとおり。
(No.3のコードをありがたく使わせていただきます)

|①|  |②|③|  |  |  |④|  |  |⑤|
+―+―+―+―+―+―+―+―+―+―+―+
|a|a|b|c|c|c|c|d|d|d|e|
+―+―+―+―+―+―+―+―+―+―+―+

▼1巡目
    b[j]←a[i]  // ①の'a'を配列bに転記
    n←1
    k←i+1      // kは①の右隣のa[2]を指すようにして
    while(k<=m)and(a[k]=a[i]) 
        n←n+1
        k←k+1  // kを2,3と変化させる
    endwhile    // 'a'でない文字がa[3]で見つかったのでループ終了
                // 連続文字数nは2

▼2巡目
    b[j]←a[i]  // ②の'b'を配列bに転記
    n←1
    k←i+1      // kは②の右隣のa[4]を指すようにして
    while(k<=m)and(a[k]=a[i]) // 'b'でない文字がa[4]で見つかったのでループしない
        n←n+1
        k←k+1
    endwhile
                // 連続文字数nは1

▼3巡目
    b[j]←a[i]  // ③の'c'を配列bに転記
    n←1
    k←i+1      // kは③の右隣のa[5]を指すようにして
    while(k<=m)and(a[k]=a[i]) 
        n←n+1
        k←k+1  // kを5,6,7,8と変化させる。
    endwhile    // 'c'でない文字がa[8]で見つかったのでループ終了
                // 連続文字数nは4

▼4巡目
    b[j]←a[i]  // ④の'd'を配列bに転記
    n←1
    k←i+1      // kは④の右隣のa[9]を指すようにして
    while(k<=m)and(a[k]=a[i]) 
        n←n+1
        k←k+1  // kを9,10,11と変化させる。
    endwhile    // 'd'ではない文字がa[11]で見つかったのでループ終了
                // 連続文字数nは3

▼5巡目
    b[j]←a[i]  // ⑤の'e'を配列bに転記
    n←1
    k←i+1      // kは⑤の右隣のa[12]を指すようにして
    while(k<=m)and(a[k]=a[i]) // k=12は配列長を越えたのでループしない
        n←n+1
        k←k+1
    endwhile
                // 連続文字数nは1
2024.05.28 22:06
jjon-comさん 
FE ゴールドマイスター
(No.8)
> i←k  /* ①より、次に走査する配列 a の位置
> とありますが、 k←k+1 では不可なのでしょうか?

ダメです。

この疑似言語のコード全体を眺めてください。

変数iへの代入(代入文においてiが左辺に置かれているもの)は次の2箇所にしか登場しません。

i←1 (aの配列)
i←k  /* ①より、次に走査する配列 a の位置

もし上記の i←k が「k←   」というコードに置き換えられるしたら、
変数iはずっと1のまま変化しなくてもかまわない、ということになります。
2024.05.28 22:20
boyonboyonさん 
FE シルバーマイスター
(No.9)
>また
>i←k  /* ①より、次に走査する配列 a の位置
>とありますが、 k←k+1 では不可なのでしょうか?

ループの中の動きは、No.7 で詳しく説明されているので、この部分だけ補足します。

同じ文字が連続しないで内側のループを通らない時を考えると分かりやすいです。
内側のループを省略して書くと

while(i<=m)    /*配列 a の末尾になるまで繰り返します。
    j←j+1
    b[j]←a[i]  /*配列のコピー
    n←1        /*1文字目の代入です。(1個目)
*    k←i+1      /*配列 a の現在位置の次
(ループ省略)
*    i←k  /* ①より、次に走査する配列 a の位置
endwhile

*の所でi←i+1
になり、上記の処理は配列をそのままコピーすることになります。

ついでにプログラムの流れに沿ってのi,j,k,nの変化です。
□はスペースだと思ってください。桁そろえです。

1~3巡目
i 1|□□□□□□3|□□□4|□□□□□□□□□□8|
j 0|1□□□□2□|3□□□|4□□□□□□□□5□|
n □|□1□2□□□|□1□□|□1□2□3□4□□□|
k □|□□2□3□□|□□4□|□□5□6□7□8□□|

4~5巡目
i |□□□□□□□□□□11|□□□□12|
j |6□□□□□□□□7□□|8□□□□□|
n |□1□2□□3□□□□□|□1□□□□|
k |□□9□10□11□□□|□□12□□|
2024.05.28 23:25
まきさん  
(No.10)
>お二方
解説ありがとうございました。
もう少しだけ聞きたいことがあります

5巡目の時
 while(k<= m)and(a[k]=a[i])
       12  12      12   12 
n←n+1
k←k+1
endwhile

 /k=12の時に配列の長さを超えたのでループせず走査終了/

 i←k
12  12
aの配列←次に走査する配列aの位置

□配列の位置が決まる→プログラム終了ということでしょうか?
またこれでaの配列は11文字というのが分かったのでしょうか?
2024.05.29 17:09
jjon-comさん 
FE ゴールドマイスター
(No.11)
> 配列の位置が決まる→プログラム終了ということでしょうか?
> またこれでaの配列は11文字というのが分かったのでしょうか?

配列aの長さが11だというのは最初から分かっています。
> 文字列a(a[1]~a[m])中で
と問題文に書いてありますから,配列aの中身が今回例示されているデータである場合,配列aの長さは11であり,その11が変数mに格納されて渡されることは,この問題を解く上での前提になっています。

配列aの先頭から末尾まで走査すれば(変数iが1~11まで動き,12になったら)プログラム終了です。
プログラムが実行し続けるか/終了するかを判定しているのが,外側の while(i<=m) 文です。

----
> 5巡目の時
>  while(k<= m)and(a[k]=a[i])
>        12  12      12   12 

ではなく,

> 5巡目の時
>  while(k<= m)and(a[k]=a[i])
>        12  11

です。
(k<= m) and (a[k]=a[i]) のように条件式が併記されている場合,
左の条件式が先に判定され,右の条件式が後に判定されます。

論理積 and は左右の条件式が両方ともに真のときだけ全体が真となります。
左の条件式 12 <= 11 が偽であったなら,
この時点で全体が真になることはありえないことが判明するので,
右の条件式 a[k]=a[i] は判定すらされません。

もし仮に,この条件式が次のようであったとしましょう。

while(a[k]=a[i])and(k<= m)
        12   11

この場合,左の条件式を判定する際に,
a[12]という存在しない要素を参照してしまうのでこのプログラムはエラーになります。

結論です。
while(a[k]=a[i])and(k<= m)

while(k<= m)and(a[k]=a[i])

同じ意味ではありません。

前者は配列の範囲外を指してエラーになってしまう誤ったコードであり,
後者が正しいコードになります。
2024.05.29 23:33
まきさん  
(No.12)
">jjon-comさん
解説ありがとうございました。
結局
5巡目の時
 while(k<= m)and(a[k]=a[i])
       12  12      12   12 
n←n+1
k←k+1
endwhile

 /k=12の時に配列の長さを超えたのでループせず走査終了/

 i←k
11  11
aの配列←次に走査する配列aの位置ということになるのでしょうか?
2024.05.30 21:19
jjon-comさん 
FE ゴールドマイスター
(No.13)
> 配列aの長さは11であり,その11が変数mに格納されて渡される
すなわち m=11 だと No.11 で述べているのに,

> 結局
> 5巡目の時
>  while(k<= m)and(a[k]=a[i])
>        12  12      12   12 
のように mに12を充てている意味が分かりません。

> k←i+1      // kは⑤の右隣のa[12]を指すようにして
> while(k<=m)and(a[k]=a[i]) // k=12は配列長を越えたのでループしない

のように whileに入る直前の kの値は i+1 であることは明らかなのに,

> 結局
> 5巡目の時
>  while(k<= m)and(a[k]=a[i])
>        12  12      12   12 
のように kとiに同じ12を充てている意味が分かりません。
2024.05.30 22:46
boyonboyonさん 
FE シルバーマイスター
(No.14)
No.12 を読ませていただいた限りでは、No.10 とほとんど変わっていないようです。
・・・最後の12が11に変わっただけかと...
No.11 の説明をもっとよくお読みになった方が良いと思います。
以下、補足説明です。

5巡目に入るときは、i=11,j=7,k=11 の状態です。
あと、この問題の設定では、m=11 これは変化しません。定数のようなものです。
(5巡目)
while(i<=m)     /*i=11,m=11なので「真」ループに入ります。
    j←j+1      /* j=8  になります。
    b[j]←a[i]  /* b[8]←a[11] aの末尾が、bに代入されます。aからbへの変換はここで終了です。
                /* あとは、ループを抜けるだけです。
    n←1        
    k←i+1      /* k=12 になります。
    
    while((k<=m)and(a[k]=a[i])) /* k=12,m=11 より  k<=m が「偽」なので

                ループに入りません。①へ
        n←n+1
        k←k+1
    endwhile
①:n=1なので、以下のif文は実行されず、②へ
    if(n>=3)
        j←j+1
        b[j]←c[n]
    elseif(n=2)
        j←j+1
        b[j]←a[i+1]
    endif

     i←k /* i=12 になります。
endwhile  /* ループの最初に戻り6巡目に入ろうとしますが、

while(i<=m)    /*i=12,m=11なので「偽」、ループに入らず
・・・・・・(略)
endwhileの次になります。
以降は書いてないので分かりません。とりあえず書いてある所の処理は終了します。
2024.05.30 23:22
まきさん  
(No.15)
">お二方"
解説ありがとうございました。
もう一度やり直して疑問点があればお聞きします。
時間をください。
2024.05.31 19:57
どんちゃんさん 
(No.16)
文字列の圧縮、時間をかければもちろんわかりますけど、
こんな大学入試の大問みたいなガッツリ問題、本番賞味5分の世界で解けるのかなあwwって思ったりします。
本番、みんなどう向き合っているんだろ、、って思ったりしますよねw
2024.05.31 20:54
こん黒さん 
(No.17)
試験のヒントは日本語で記述された説明文に集約されているので安心していいですよ。
というより日本語読解力の方が重要でコード自体にはあまり本質はない印象です。

極端な例ですが、私(非プログラマー)は科目Bを800点強で合格しましたが、日本語解説の無い当該のコードを読んでも1ミリも理解出来ません。
2024.06.01 00:27
どんちゃんさん 
(No.18)
試験のヒントは日本語で記述された説明文に集約されているので安心していいですよ。
というより日本語読解力の方が重要
⇒全面同意みが深すぎます。笑 名言
2024.06.01 01:10
まきさん  
(No.19)
>こん黒さん、どんちゃんさん
コメントありがとうございます。
大滝本でも文字圧縮の問題はあるんですよね・・・・
2024.06.02 17:29
まきさん 
(No.20)
橋本本やるか‥
2024.06.04 22:00

返信投稿用フォーム

スパム防止のためにスレッド作成日から30日経過したスレッドへの投稿はできません。

その他のスレッド


Pagetop