paiza レベルアップ問題集 「STEP: 3 数列の何番目にある?」をPythonとGASで解いてみた

この記事を読むことで、PythonにおけるIF文・Forループの基本的な書き方と、リスト(配列)の「指定の文字」が「どこに格納されているのか」を、トレースしながら該当の添字を調べることが出来ます。

このコーナーでは、学習コンテンツpaizaラーニングレベルアップ問題集をPythonとGASの両方で解いて全コードの解説をしています。
PythonとGASの両方のコードを用いて、全コード及び部分的にも可能な限り詳細に記載いたしました。

GASはスプレッドシートを使っています。
GASはGoogle Apps Scriptと言って、JavaScriptの文法をベースにしているので、JavaScriptの学習中の方にもお役立て出来るかも知れません。

サイトマップはこちらから

paizaレベルアップ問題集でPythonとGASを解いて見たに戻る
メインメニューに戻る
Python自作サンプル
GASサンプル
基本情報技術者試験

paizaでの解答はPythonで行いましたが、この記事ではPythonのコードと共に、同じ問題を現在学習中のGASだったらどう解くのか、スプレッドシートでバインドして作ってみました。

数列の何番目にある? (paizaランク D 相当)

問題:
長さ N の数列 a (a_1, a_2, …, a_N) が与えられます。
この数列の何番目に 1 があるか出力してください。
数列の 1 つ目の要素を 1 番目とし、数列には必ず 1 がひとつだけ含まれることとします。

この記事では、入力例3でNにリスト長さが「6」、リストに「8 2 3 8 1 3」が与えられたという条件で解いて行きます。

入力例3
6
8 2 3 8 1 3

出力例3
5

ではまず、Pythonで解いてみます。

今回は、paiza.ioを使って解きます。paiza.ioの使い方はこちらから。

<<Pythonでの解き方>>

下準備として、paiza.ioにこの様に入力します。

手順として、
1:標準入力でNを取得
2:標準入力でリストを取得
3:変数numに「1」が含まれている所の要素番号にNを仮に設定(リストの要素番号はN-1までなので。)
4:ループで「1」が含まれている位置を探索する
5:先頭の要素が0なので、1を加えて出力する

手順3ですが、要素番号はこの例(N=6)の場合、0,1,2,3,4,5です。
つまり、求める要素番号が6になることは問題文の設定上、絶対にありません。
なので、numをNで初期化しています。

では、コードを見て行きます。
リストの要素とその中身をトレースしたコードと実行結果です。

#標準入力でNを取得
N=int(input())


#標準入力でリストを取得
array=list(map(int,input().rstrip().split(' ')))

#変数numに「1」が含まれている所の要素番号にNを仮に設定(リストの要素番号はN-1までなので。)
num=N

#リストを出力
print(array)

#ループで「1」が含まれている位置を探索する
for i in range(N):
    
    #ループでの探索のトレース
    print('要素'+str(i)+'は「'+str(array[i])+'」です。')
    
    if array[i]==1:
        num=i
        print('見つかった!!インデックス'+str(i)+'は「'+str(i+1)+'」番目')

#先頭の要素が0なので、1を加えて出力する
print(num+1)

このトレースコードについて深く知りたい方の多くは基本情報技術者試験を目指されている方か、既にお持ちの方、または講師の方かもしれませんので、宜しければ当ブログの基本情報技術者試験トップページをご覧下さい。アルゴリズムや午後問題の勉強の仕方やオススメ参考書について、かなり詳しく書いています。

では、このコードの話に戻します。
このままでは、paizaの問題の「1がリストの何番目にあるのか」に対して余分なコードがあるので、コメントアウトします。


#標準入力でNを取得
N=int(input())


#標準入力でリストを取得
array=list(map(int,input().rstrip().split(' ')))

#変数numに「1」が含まれている所の要素番号にNを仮に設定(リストの要素番号はN-1まで)
num=N

#リストを出力
#print(array)

#ループで「1」が含まれている位置を探索する
for i in range(N):
    
    #ループでの探索のトレース
    #print('要素'+str(i)+'は「'+str(array[i])+'」です。')
    
    if array[i]==1:
        num=i
        #print('見つかった!!インデックス'+str(i)+'は「'+str(i+1)+'」番目')

#先頭の要素が0なので、1を加えて出力する
print(num+1)        

ioの出力確認をしてコードを提出。

これで無事正解しました。

<<GASでの解き方>>

では、同じ問題をGASで解いてみます。

まず、スプレッドシートにこの様に配置しました。

黄色いセルの所に配列の最大値を出力します。

※スプレッドシートに表示する場合は、ループを使って一次元配列ではなく、二次元配列としてからの配列に追加をして作成します※

手順はこのようになります。

1:スプレッドシートからアクティブシートをアクセスする

2:緑色のセル(B1)にある、リストの長さNを取得(この例の場合N=6)

3:配列arrayを宣言して、灰色のセルの範囲の配列を格納する

4:ログで配列を取得できたことを確認

5:上の配列の中から「1」がある位置を探索して見つかった場所をnumに代入する
配列の添字が0,1,2,…N-1までなので、numをあり得ないNで初期化

6:ループとIFで「1」の位置をトレースしながら探索

7:numをログで出力して確認

8:配列の添字は0番目から始まるので、numに1を加える

9:numがインクリメント(加算)出来たことをログ出力して確認

10:スプレッドシート格納用に配列num2を宣言

11:num2にnumを二次元配列になるように格納

12:スプレッドシート出力前にnum2を確認

13:スプレッドシートの黄色いセルにnum2を出力

手順1: スプレッドシートからアクティブシートをアクセスする

const ss=SpreadsheetApp.getActiveSheet();

ここで定数ssにSpreadsheetAppから階層を辿ってアクティブシートにアクセスしています。

手順2:緑色のセル(B1)にある、リストの長さNを取得(この例の場合N=6)

const N=ss.getRange(1,2).getValue();

手順3:配列arrayを宣言して、灰色のセルの範囲の配列を格納する

const array = ss.getRange(2, 2, 1, N).getValues();

手順4:ログで配列を取得できたことを確認

console.log(array);

手順5:上の配列の中から「1」がある位置を探索して見つかった場所をnumに代入する
配列の添字が0,1,2,…N-1までなので、numをあり得ないNで初期化
この例ですと、N=6なので、このリストの添字は「0,1,2,3,4,5」です。
なので、添字が6になることはあり得ません。

let num=N;

手順6:ループとIFで「1」の位置をトレースしながら探索

//ループとIFで「1」の位置をトレースしながら探索
  for(let i=0;i<N;i++){
    if(array[0][i]==1){
      num=i
      console.log(`見つかった!!インデックス+「${i}」+は【${i+1}】番目!!!`);
    }
    console.log(`要素${i}は、「${array[0][i]}」です。`);
  }

スプレッドシートでは2次元配列で格納されているので、array[0][i]と記述して、配列の1行目をループで配列の中身が1かどうか確認しています。

もしもarray[0][i]が「1」と等しかったら、変数numに[i]を格納しています。
その後conole.logで、「見つかった!!インデックス+「${i}」+は【${i+1}】番目!!!」と表示しています。
「`」は、[Shift]+[@]です。
数値が入る所に${}と記述しています。

手順7:numをログで出力して確認

console.log(num);

手順8:配列の要素は0番目から始まるので、numに1を加える

num++;

手順9:numがインクリメント(加算)出来たことをログ出力して確認

console.log(num);

手順10:スプレッドシート格納用に配列num2を宣言

let num2=[];

スプレッドシートはタテとヨコの二次元配列で格納しているので、格納する前に二次元配列にします。

手順11:num2にnumを二次元配列になるように格納

num2.push([num]);

手順12:スプレッドシート出力前にnum2を確認

console.log(num2);

手順13:スプレッドシートの黄色いセルにnum2を出力

ss.getRange(4,2).setValue(num2);

スプレッドシートの実行結果です。

GASでの全コードはこちらになります。

function loop19(){
  
  //スプレッドシートからアクティブシートをアクセスする
  const ss=SpreadsheetApp.getActiveSheet();

  //緑色のセル(B1)にある、リストの長さNを取得(この例の場合N=6)
  const N=ss.getRange(1,2).getValue();

  //配列arrayを宣言して、灰色のセルの範囲の配列を格納する
  const array=ss.getRange(2,2,1,N).getValues();

  //ログで配列を取得できたことを確認
  console.log(array);
  

  //上の配列の中から「1」がある位置を探索して見つかった場所をnumに代入する
  //配列の添字が0,1,2,…N-1までなので、numをあり得ないNで初期化
  let num=N;

  //ループとIFで「1」の位置をトレースしながら探索
  for(let i=0;i<N;i++){
    if(array[0][i]==1){
      num=i
      console.log(`見つかった!!インデックス+「${i}」+は【${i+1}】番目!!!`);
    }
    console.log(`要素${i}は、「${array[0][i]}」です。`);
  }

  //numをログで出力して確認
  console.log(num);

  //配列の添字は0番目から始まるので、numに1を加える
  num++;

  //numがインクリメント(加算)出来たことをログ出力して確認
  console.log(num);

  //スプレッドシート格納用に配列num2を宣言
  let num2=[];

  //num2にnumを二次元配列になるように格納
  num2.push([num]);

  //スプレッドシート出力前にnum2を確認
  console.log(num2);

  //スプレッドシートの黄色いセルにnum2を出力
  ss.getRange(4,2).setValue(num2);
}

宜しかったらコピペしてアレンジして見て下さい。

お疲れ様でした、ブレイクタイムフォトはこちらになります。

恵比寿ガーデンプレイス「俺のBakery&Cafe」

■ 参考文献の紹介■

じっくり丁寧にPythonを学びたい方向け。
まずはpaizaラーニングなどの学習コンテンツで学んで、基礎をマスターしたら、この本でじっくりと初級から中級レベルを目指せます。

初めてGASを学ぶ方向け。
スプレッドシートの基本的な使い方からGASのベースとなるJavaScriptの基礎文法、GASでの初歩的なプログラミングを学べます。

GASに少し慣れて来たら、基礎固めとリファレンスとしてこの本でじっくり学べます。

サイトマップはこちらから

paizaレベルアップ問題集でPythonとGASを解いて見たに戻る
メインメニューに戻る
Python自作サンプル
GASサンプル
基本情報技術者試験

←前の問題へ                  次の問題へ→