<ねこフォーム実践1>就職セミナーアンケート

この記事では、GAS(Google Apps script)を使って、おおよそのセミナーや、企業説明会で使える参加者向けのアンケートを作成します。

お世話になっているサイトは、いつも隣にITのお仕事さんの

GASでGoogleフォームを一発で作成するツールを作る

です。

まず、下記のような3枚のスプレッドシートを用意します。

・シート「トップ画面」

ここには、ボタンを設置して、後でこのボタンを押すとフォームが作れるようにします。

・シート「フォームのタイトルと説明の情報」

ここには、作成するフォームのタイトルと説明文を入れます。

シート「項目データ」

ここには、アンケート回答者がラジオボタン、チェックボックス、リストアイテムから選択出来るようスプレッドシートに配置しています。

このデータを二次元配列として取得して、各列ごとに1次元配列に変換して、ラジオボタンなどから選択出来るようにしています。

まず、スプレッドシートのボタンを押すとフォームが作れる関数、「pushButton」を作ります。

シート「フォームのタイトルと説明の情報」を二次元配列arrayとして取得して、array[0][1]をタイトル、array[1][1]をフォームの説明文として取得しています。

また、フォームに氏名とメールアドレスのテキストアイテムを追加します。

メールアドレスは@が含まれているなど、メールアドレスとして正しいかどうかを検証しています。

このメールアドレスとして検証するという部分については、

<ねこフォーム4>ねこあつめフォームに「メールアドレス」を追加する

で詳細に掲載致しました。

//このボタンを押すと、フォームが作成される。
function pushButton() {
  
  //シート「フォームのタイトルと説明の情報」からフォームのタイトルと説明を取得
  const ss=SpreadsheetApp.getActiveSpreadsheet();
  const array=ss.getSheetByName('フォームのタイトルと説明の情報').getDataRange().getValues();
  const formTitle=array[0][1];//タイトル
  const formDescription=array[1][1];//フォームの説明文

  
  //フォームを作成。タイトルにはシート「フォームのタイトルと説明の情報」のvalues[0][1]から取得される
  const form=FormApp.create(formTitle);

  //フォームの説明。フォームの説明文にはシート「フォームのタイトルと説明の情報」のvalues[1][1]から取得される
  form.setDescription(formDescription);


  //以下、フォームの設問の項目
  form.addTextItem().setTitle('氏名').setRequired(true); //氏名は入力必須項目にしている。

  const validationEmail=FormApp.createTextValidation().requireTextIsEmail().build();//eメールアドレスが正しいか検証
  form.addTextItem().setTitle('メールアドレス').setRequired(true).setValidation(validationEmail);
}

では、いよいよスプレッドシートのシート「項目データ」からデータを取得して、フォームを作成して行きます。

まず、シート「項目データ」を二次元配列として取得するために、下記のコードを書きました。

//以下、シート「項目データ」から取得している。
  //シート「項目データ」からフォームの質問の項目を二次元配列として取得し、その二次元配列のタイトル行を削除する
  const dataValues=ss.getSheetByName('項目データ').getDataRange().getValues();
  dataValues.shift()

このコードでは、定数dataValuesにシートを二次元配列として取得したデータを格納して、先頭のタイトル行をshisft()で削除しています。

この二次元配列の各行をフォームのアイテムから選択出来るように一次元配列に変換して、更に空白行を取り除く関数generateArrayを作成しました。

引数に二次元配列のデータとその行を指定して関数generateArrayに送ります。

ここではmapで一次元配列に変換して、filterで空白行を取り除いています。

/**
 * フォームのアイテムの内容をスプレッドシートから取得する関数
 * シート「項目データ」の値を取得した二次元配列から、指定の列のデータを抜き出し一次元配列を構成する。その為、mapを使っている。
 * その際、列の空白データを削除するためにfilterも使っている。 
 * 
 * @param{Object[][]}シートのデータを二次元配列化とした配列
 * @param{number}配列の列数(0以上のインデックス)
 * @return{Object{}}指定の列(見出しを除く)のデータによる一次元配列
 */
function generateArray(values,column){
  return values.map(record=>record[column]).filter(value=>value);
}

関数呼び出し時には、下記のように指定しました。

A列「性別」は、ラジオボタンで、

generateArray(dataValues,0)

と記述し、引数に二次元配列のデータと列数を指定することで「性別」が選択出来ます。

form.addMultipleChoiceItem()    //ラジオボタンはシート「項目データ」の「0列目」から取得している。
    .setTitle('性別')
    .setChoiceValues(generateArray(dataValues,0))
    .setRequired(true);

テキストアイテムで学校名を入力します。

form.addTextItem().setTitle('在学、卒業の学校名').setRequired(true);//入力はテキストアイテム

B列「学部」の呼び出しは、ラジオボタンで、

generateArray(dataValues,1)

です。その他の学部も選択記載出来るようにしています。

form.addMultipleChoiceItem()    //ラジオボタンはシート「項目データー」の「1列目」から取得している
    .setTitle('学部')
    .setChoiceValues(generateArray(dataValues,1))
    .showOtherOption(true)//その他の選択肢

学科・コースはテキストアイテムで入力します。

form.addTextItem().setTitle('学科・コース');

C列「卒業・在学の区分」はラジオボタン(※必須)で、

generateArray(dataValues,2)

です。その他の項目も選択出来ます。

form.addMultipleChoiceItem()    //ラジオボタンはシート「項目データ」の「2列目」から取得している
    .setTitle('卒業・在学の区分')
    .setChoiceValues(generateArray(dataValues,2))
    .showOtherOption(true)//その他の選択肢
    .setRequired(true);

D列「出身・在住の都道府県」はリストアイテム(※必須)で、

generateArray(dataValues,3)

です。

これはリストアイテムのタイトルを変えて2回呼び出しています。

1回目の呼び出しはお住まい、2回目は出身です。

form.addListItem()  //リストアイテムはシート「項目データ」の「3列目」から取得している  
    .setTitle('お住まいの都道府県は?')
    .setChoiceValues(generateArray(dataValues,3))
    .setRequired(true);


  form.addListItem()   //リストアイテムはシート「項目データ」の「3列目」から取得している
    .setTitle('ご出身の都道府県は?')
    .setChoiceValues(generateArray(dataValues,3))
    .setRequired(true);

E列「当社を知った媒体」はチェックボックス(※必須)で、

generateArray(dataValues,4)

です。

これもその他を選択出来るようにしています。

form.addCheckboxItem()    //チェックボックスはシート「項目データ」の「4列目」から取得している
    .setTitle('当社を知った媒体はどちらでしょうか。')
    .setChoiceValues(generateArray(dataValues,4))
    .showOtherOption(true)//その他の選択肢
    .setRequired(true);

これ以降は、セミナーの内容が5段階評価で選択出来るようにスケールアイテムを使っています。(※必須)

//以下、スケールアイテム
  
  form.addScaleItem()
    .setTitle('講師の声の聞き取りやすさ     1: 全く良くない  〜  5: 大変良い')
    .setBounds(1,5)
    .setRequired(true);


  form.addScaleItem()
    .setTitle('講師の説明の分かりやすさ     1: 全く分からない  〜  5: 大変分かりやすい')
    .setBounds(1,5)
    .setRequired(true);


  form.addScaleItem()
    .setTitle('スタッフの身だしなみ     1: 全く良くない  〜  5: 大変良い')
    .setBounds(1,5)
    .setRequired(true);

  form.addScaleItem()
    .setTitle('スタッフの対応    1: 全く良くない  〜  5: 大変良い')
    .setBounds(1,5)
    .setRequired(true);


    form.addScaleItem()
    .setTitle('当社志望度    1: 低い  〜  5: 高い')
    .setBounds(1,5)
    .setRequired(true);

最後は自由に記入できる段落入力アイテムです。

form.addParagraphTextItem().setTitle('ご意見ご要望');//段落テキストアイテム

ここまでで実行すると、このようなフォームが作れます。これは目のマークでプレビューを押した画面です。

マイドライブに保存する場合はここまででも良いのですが、指定のドライブに保存したい場合は、プロパティストアというものを使って、フォルダIDをFOLDER_IDという文字列に保存します。

フォルダIDはこちらになります。

このモザイク部分32桁をこちらのコードでFOLDER_IDに保存します。
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXを実際のフォルダーIDに置き換えて下さい。特定のフォルダに指定する場合は、pushButtonを押すよりも先にこちらを実行して下さい。

//フォームを保存したいドライブのIDを指定して、1番最初に実行する。
function setScriptProperty(){
  PropertiesService.getScriptProperties().setProperty('FOLDER_ID','XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
}

その実行画面です。

この様に何も起こらないので不安になるかと思います。

そこで、FOLDER_IDに格納出来たのか確認するコードを書きました。

//プロパティストアにフォルダIDが格納されたことを確認する
function getScriptProperty(){
  const folderid=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
  console.log(folderid);

実行結果です。先ほどのフォルダーID32桁が無事に表示されましたので、モザイク処理を施しました。

あとはメインの関数にこの4行のコードを追記します。

プロパティストアからFOLDER_IDを取り出して、フォームをそこに格納し、マイドライブに出来てしまったフォームの方は削除します。

//ここの4行ををコメントアウトすることで、マイドライブに保存が出来る。
  //フォームを指定のドライブに保存する
  const id=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');//格納するフォルダIDを取り出す
  const formFile=DriveApp.getFileById(form.getId());//作成したフォームをオブジェクトとして取得
  DriveApp.getFolderById(id).addFile(formFile);//指定のフォルダにFileオブジェクトを追加する
  DriveApp.getRootFolder().removeFile(formFile);//マイフォルダからFileオブジェクトを削除する

コメントにもある様、マイドライブ(ルードディレクトリ)に保存したい場合は、一旦コメントアウトをしておいても状況に寄っては宜しいかもしれません。

ここまでの説明で、もう少し詳しくプロパティストアについて知りたいという方は、

<ねこフォーム2>GASで作成したフォームを指定のフォルダに格納する

をご覧ください。

では、これまでのコードをまとめます。

/**
 * フォームのアイテムの内容をスプレッドシートから取得する関数
 * シート「項目データ」の値を取得した二次元配列から、指定の列のデータを抜き出し一次元配列を構成する。その為、mapを使っている。
 * その際、列の空白データを削除するためにfilterも使っている。 
 * 
 * @param{Object[][]}シートのデータを二次元配列化とした配列
 * @param{number}配列の列数(0以上のインデックス)
 * @return{Object{}}指定の列(見出しを除く)のデータによる一次元配列
 */
function generateArray(values,column){
  return values.map(record=>record[column]).filter(value=>value);
}


//このボタンを押すと、フォームが作成される。
function pushButton() {
  
  //シート「フォームのタイトルと説明の情報」からフォームのタイトルと説明を取得
  const ss=SpreadsheetApp.getActiveSpreadsheet();
  const array=ss.getSheetByName('フォームのタイトルと説明の情報').getDataRange().getValues();
  const formTitle=array[0][1];//タイトル
  const formDescription=array[1][1];//フォームの説明文

  
  //フォームを作成。タイトルにはシート「フォームのタイトルと説明の情報」のvalues[0][1]から取得される
  const form=FormApp.create(formTitle);

  //フォームの説明。フォームの説明文にはシート「フォームのタイトルと説明の情報」のvalues[1][1]から取得される
  form.setDescription(formDescription);


  //以下、フォームの設問の項目
  form.addTextItem().setTitle('氏名').setRequired(true); //氏名は入力必須項目にしている。

  const validationEmail=FormApp.createTextValidation().requireTextIsEmail().build();//eメールアドレスが正しいか検証
  form.addTextItem().setTitle('メールアドレス').setRequired(true).setValidation(validationEmail);

  
  //以下、シート「項目データ」から取得している。
  //シート「項目データ」からフォームの質問の項目を二次元配列として取得し、その二次元配列のタイトル行を削除する
  const dataValues=ss.getSheetByName('項目データ').getDataRange().getValues();
  dataValues.shift()
  

  form.addMultipleChoiceItem()    //ラジオボタンはシート「項目データ」の「0列目」から取得している。
    .setTitle('性別')
    .setChoiceValues(generateArray(dataValues,0))
    .setRequired(true);
  
  form.addTextItem().setTitle('在学、卒業の学校名').setRequired(true);//入力はテキストアイテム

  form.addMultipleChoiceItem()    //ラジオボタンはシート「項目データー」の「1列目」から取得している
    .setTitle('学部')
    .setChoiceValues(generateArray(dataValues,1))
    .showOtherOption(true)//その他の選択肢

  form.addTextItem().setTitle('学科・コース');


  form.addMultipleChoiceItem()    //ラジオボタンはシート「項目データ」の「2列目」から取得している
    .setTitle('卒業・在学の区分')
    .setChoiceValues(generateArray(dataValues,2))
    .showOtherOption(true)//その他の選択肢
    .setRequired(true);


  
  form.addListItem()  //リストアイテムはシート「項目データ」の「3列目」から取得している  
    .setTitle('お住まいの都道府県は?')
    .setChoiceValues(generateArray(dataValues,3))
    .setRequired(true);


  form.addListItem()   //リストアイテムはシート「項目データ」の「3列目」から取得している
    .setTitle('ご出身の都道府県は?')
    .setChoiceValues(generateArray(dataValues,3))
    .setRequired(true);


  form.addCheckboxItem()    //チェックボックスはシート「項目データ」の「4列目」から取得している
    .setTitle('当社を知った媒体はどちらでしょうか。')
    .setChoiceValues(generateArray(dataValues,4))
    .showOtherOption(true)//その他の選択肢
    .setRequired(true);


  //以下、スケールアイテム
  
  form.addScaleItem()
    .setTitle('講師の声の聞き取りやすさ     1: 全く良くない  〜  5: 大変良い')
    .setBounds(1,5)
    .setRequired(true);


  form.addScaleItem()
    .setTitle('講師の説明の分かりやすさ     1: 全く分からない  〜  5: 大変分かりやすい')
    .setBounds(1,5)
    .setRequired(true);


  form.addScaleItem()
    .setTitle('スタッフの身だしなみ     1: 全く良くない  〜  5: 大変良い')
    .setBounds(1,5)
    .setRequired(true);

  form.addScaleItem()
    .setTitle('スタッフの対応    1: 全く良くない  〜  5: 大変良い')
    .setBounds(1,5)
    .setRequired(true);


    form.addScaleItem()
    .setTitle('当社志望度    1: 低い  〜  5: 高い')
    .setBounds(1,5)
    .setRequired(true);



  form.addParagraphTextItem().setTitle('ご意見ご要望');//段落テキストアイテム
  

  
  //ここの4行ををコメントアウトすることで、マイドライブに保存が出来る。
  //フォームを指定のドライブに保存する
  const id=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');//格納するフォルダIDを取り出す
  const formFile=DriveApp.getFileById(form.getId());//作成したフォームをオブジェクトとして取得
  DriveApp.getFolderById(id).addFile(formFile);//指定のフォルダにFileオブジェクトを追加する
  DriveApp.getRootFolder().removeFile(formFile);//マイフォルダからFileオブジェクトを削除する
  

}


//フォームを保存したいドライブのIDを指定して、1番最初に実行する。
function setScriptProperty(){
  PropertiesService.getScriptProperties().setProperty('FOLDER_ID','XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
}

//プロパティストアにフォルダIDが格納されたことを確認する
function getScriptProperty(){
  const folderid=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
  console.log(folderid);

}

あとはスプレッドシートのトップ画面のボタンの右上3点リーダーからスクリプトを「pushButton」に割り当てて押すと、あなたが指定したフォルダ、または上記4行をコメントアウトした場合はマイドライブに保存されます。

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

恵比寿ガーデンプレイス、フランスのクリスタルメーカー、バカラのシャンデリア。
カメラはOLYMPUSのミラーレス一眼。

この写真ムービーは、下記の記事でご覧になれます。

恵比寿ガーデンプレイス、バカラのシャンデリア

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

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

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

GASサンプル集に戻る
メインメニューに戻る
これからプログラミングを始める方へ
基本情報技術者へ
自己紹介

ねこフォーム実践編2プログラミングアンケートに進む→

<ねこフォーム7>ねこあつめフォームに「プルダウンリスト」を追加する

この記事では、GAS(Google Apps script)でねこあつめフォームに「プルダウンリスト」を追加します。
また、ラジオボタンや、チェックボックスも、スプレッドシートからデータを取得してフォームに表示出来るように致します。

お世話になっているサイトは、いつも隣にITのお仕事さんの

GASでGoogleフォームにプルダウンリストの質問を追加する方法

Googleフォームの質問の選択肢をスプレッドシートのデータから生成するGAS関数の作り方

です。

まずは、前回のおさらいをします。
チェックボックスを追加するのに、下記のコードを追加しました。

//←チェックボックスを追加する
  form.addCheckboxItem()
    .setTitle('種類は何系?(チェックボックス)')
    .setChoiceValues(['みけ','とら']) 
    .showOtherOption(true)//その他のチェックボックスを作っている
    .setRequired(true); 

実行して、プレビュー画面です。

前回のコードのまとめです。

function myFunction() {

  //SpreadsheetAppから現在のスプレッドシートにアクセス
  const ss=SpreadsheetApp.getActiveSpreadsheet();

  //シート名「イベント概要」のデータを配列として取得する
  const values=ss.getSheetByName('イベント概要').getDataRange().getValues();
  const formTitle=values[0][1];//タイトル
  const formDescription=values[1][1];//概要
  
  //フォームを作成
  const form=FormApp.create(formTitle);

  //ここでプロパティストアに格納したFOLDER_IDを使って、指定のフォルダにフォームを作成する
  const id=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');//idにFOLDER_IDを格納する
  const formFile=DriveApp.getFileById(form.getId());//作成したフォームのIDをformFileに格納する
  DriveApp.getFolderById(id).addFile(formFile);//指定のフォルダにフォームを格納する
  DriveApp.getRootFolder().removeFile(formFile);//マイドライブに作成されたフォームを削除する

  //フォームの説明を作成
  form.setDescription(formDescription);

  //テキストアイテムを追加する
  form.addTextItem().setTitle('おなまえ').setRequired(true);//trueにすることで、入力必須にしている。
  form.addTextItem().setTitle('あそんだグッズ');

  //メールアドレスのテキストアイテムを加える
  const validationEmail=FormApp.createTextValidation().requireTextIsEmail().build();
  form.addTextItem().setTitle('めあど').setRequired(true).setValidation(validationEmail);

  //ラジオボタンを加える
  form.addMultipleChoiceItem()
    .setTitle('種類は何系?(ラジオボタン)')
    .setChoiceValues(['みけ','とら'])
    .setRequired(true);

  //←チェックボックスを追加する
  form.addCheckboxItem()
    .setTitle('種類は何系?(チェックボックス)')
    .setChoiceValues(['みけ','とら']) 
    .showOtherOption(true)//その他のチェックボックスを作っている
    .setRequired(true); 

}

今回の内容に入る前に、ねこあつめ画像に癒されます。
紙袋に入った、「赤毛ねこのアンちゃんのお尻」が可愛すぎて反則なぐらいです(=^x^=)

さて、今回はスプレッドシートからデータを取得して、フォームのアイテムに反映させて、リストアイテムも新たに作ります。

スプレッドシートは、この2枚を用意します。

フォームを作成するのに使う「イベント概要」は、今まで通りこのように配置しています。

また、フォームに追加するアイテムは、シート「項目データ」にこのように配置しています。

猫ちゃん達の出身地は47都道府県なので、それを全部コードにベタ打ちするのは大変です。なので、スプレッドシートから取得するように致します。
この都道府県リストは総務省統計局さんの「2-2 都道府県別人口と人口増減率」のExcelからコピーして頂きました。

今回作成するねこあつめフォームの、「なまえ」、「1番お気に入りのグッズ」、「めあど」はプログラムからテキストアイテムを作って、上記のスプレッドシートからは、

・A列(ラジオボタン)・・・ねこ種類「みけ、とら、その他」を選択
・B列(チェックボックス)・・・他にあそんだことのあるグッズ「まるこたつ、ゆたんぽ・・・」などのグッズをチェックします。
・C列(リストアイテム)・・・ねこちゃん達の出身地を「北海道・・・沖縄」まで、プルダウンリストで選択します。

また、スプレッドシートのデータを二次元配列として取得する為、下記のコードを加えます。最初の行はタイトルなので、shift()を使って取り除いています。

//シート「項目データ」から、フォームに追加するアイテムの内容を二次元配列として取得する
  const dataValues=ss.getSheetByName('項目データ').getDataRange().getValues();
  dataValues.shift();

この二次元配列dataValuesと列数を渡すことで、その列のデータを一次元配列として取得する関数を作成しました

/**
   * シート「項目データ」の値を二次元配列として取得して、指定の列を抜き出し一次元配列を構成する
   * 
   * @param{Object[][]}シート「項目データ」を二次元配列として取得したデータ
   * @param{number} 配列の列数(0以上のインデックス)
   * @return{Object[]} 指定の列の見出しタイトル行を除くデータによる一次元配列
   * 
   */
  function generateArray(values,column){
    return values.map(record=>record[column]).filter(value=>value);
  }

関数の呼び出しは、A列の「ねこ種類」の場合は、

generateArray(dataValues,0)

と記述し、引数に二次元配列のデータと列数を指定することで「ねこ種類」が呼び出せます。

B列の「他にあそんだことのあるグッズ」の呼び出しは、

generateArray(dataValues,1)

で、

C列の「全国のねこちゃんたちの都道府県」は

generateArray(dataValues,2)

と記述して、関数を呼び出して二次元配列から一次元配列にします。

このgenerateArray関数は、「map」を使うことで、スプレッドシートのデータが二次元配列の状態で格納されているのを一次元配列にして、フォームで選択出来る形に変換しています。

また、filterを使うことで、列に含まれる空のデータを取り除くことが出来ます。
例えばA列でしたら、「みけ、とら、その他」の後は空白です。
そこでfilterを使って、データがある「みけ、とら」のみを取得してフォームで使うことが出来る様になります。

以上をまとめたコードはこちらです。

function myFunction() {

  //SpreadsheetAppから現在のスプレッドシートにアクセス
  const ss=SpreadsheetApp.getActiveSpreadsheet();

  //シート名「イベント概要」のデータを配列として取得する
  const values=ss.getSheetByName('イベント概要').getDataRange().getValues();
  const formTitle=values[0][1];//タイトル
  const formDescription=values[1][1];//概要
  
  //フォームを作成
  const form=FormApp.create(formTitle);


  //ここでプロパティストアに格納したFOLDER_IDを使って、指定のフォルダにフォームを作成する
  const id=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');//idにFOLDER_IDを格納する
  const formFile=DriveApp.getFileById(form.getId());//作成したフォームのIDをformFileに格納する
  DriveApp.getFolderById(id).addFile(formFile);//指定のフォルダにフォームを格納する
  DriveApp.getRootFolder().removeFile(formFile);//マイドライブに作成されたフォームを削除する


  //フォームの説明を作成
  form.setDescription(formDescription);

  //テキストアイテムを追加する
  form.addTextItem().setTitle('おなまえ').setRequired(true);//trueにすることで、入力必須にしている。
  form.addTextItem().setTitle('1番お気に入りのグッズ');


  //メールアドレスのテキストアイテムを加える
  const validationEmail=FormApp.createTextValidation().requireTextIsEmail().build();
  form.addTextItem().setTitle('めあど').setRequired(true).setValidation(validationEmail);


  //←シート「項目データ」から、フォームに追加するアイテムの内容を二次元配列として取得する
  const dataValues=ss.getSheetByName('項目データ').getDataRange().getValues();
  dataValues.shift();

  /**
   * シート「項目データ」の値を二次元配列として取得して、指定の列を抜き出し一次元配列を構成する
   * 
   * @param{Object[][]}シート「項目データ」を二次元配列として取得したデータ
   * @param{number} 配列の列数(0以上のインデックス)
   * @return{Object[]} 指定の列の見出しタイトル行を除くデータによる一次元配列
   * 
   */
  function generateArray(values,column){
    return values.map(record=>record[column]).filter(value=>value);
  }
  
  
  //ラジオボタンを加える
  form.addMultipleChoiceItem()
    .setTitle('ねこ種類')
    .setChoiceValues(generateArray(dataValues,0))
    .setRequired(true);

  //チェックボックスを追加する
  form.addCheckboxItem()
    .setTitle('他にあそんだグッズ')
    .setChoiceValues(generateArray(dataValues,1)) 
    .showOtherOption(true)//その他のチェックボックスを作っている
    .setRequired(true); 

  //←リストアイテムを追加する
  form.addListItem()
    .setTitle('ねこちゃんの都道府県')
    .setChoiceValues(generateArray(dataValues,2)) 
    .setRequired(true); 

}

このコードを実行した結果です。

シート「イベント概要」からは、フォームのタイトルと説明を取得しました。

シート「項目データ」からは、これらのアイテムを取得しました。

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

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

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

GASサンプル集に戻る
メインメニューに戻る
これからプログラミングを始める方へ
基本情報技術者へ
自己紹介

←前に戻るにゃん        次行くにゃん

paiza レベルアップ問題集 「STEP: 10 階乗の末尾に 0 はいくつ付く?」をPythonとGASで解いてみた

この記事を読むことで、PythonとGASでループを使って階乗の計算とその計算結果の末尾に「0」がいくつ付くのかを求めます。
階乗の計算はforループを使い、末尾の「0」はPythonでは文字列に変換して求めてからwhileループで末尾の0の数をリストを反転して求め、GASでは10と2×5がいくつ含まれているのかwhileループを使って求めます。

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

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

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

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

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

階乗の末尾に 0 はいくつ付く? (paizaランク C 相当)

問題:
整数 N が与えられます。
N の階乗 N! の末尾に 0 がいくつ付くか求め、出力してください。

この記事では、下記の入力例1の場合を例にして、整数N=100の階乗を求め、その計算結果100!の末尾に「0」がいくつ付くかを求めて行きます。

入力例1
100

出力例1
24

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

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

■ Pythonでの解き方 ■

下準備として、paiza.ioにこの様に入力します。
(入力例1をそのままioにコピーしただけ。)

手順として、

1:Nを標準入力で取り込む

2:階乗の計算結果factを1で初期化する


3:ループを使ってNの階乗N!を変数factに求める
階乗の計算で乗算する数をmultに格納する


4:factが膨大な数になり、通常の10で割っていって0の数を求める方法が適用出来ない為、文字列に変換する


5:末尾の’0’を求めるため、文字列を逆順にする


6:’0’の数を数える変数zeroを0で初期化する


7:whileループで文字列のfactのi番目が’0’というの条件を満たす間、ループを回して’0’の数を数える変数zeroをインクリメントする


8:zeroを表示

で、行います。

まずは、プログラムの各変数の動きを追いやすいように、トレースのio出力結果と、トレースのコードを添えます。

100!は、100×99×98×97×・・・×4×3×2×1で求まります。

97まで掛けたログです。

途中、飛ばします。

1まで掛けたログです。

とても膨大な数になりましたので、画像は一部のみを切り取りました。

この計算結果factは膨大すぎてそのままでは10で割って0の数を数えるということが出来ない為、文字列に変換しました。
Strを使って、文字列に出来ます。

fact=str(fact)

問題文によると、文字列の末尾から’0’を数えるので、上の画像の文字列を反転しました。文字列のリストとして反転してから数えるので、このようなコードになりました。

fact=list(reversed(fact))

その後、文字列の先頭から’0’を数えていくので、whileループでリストfact[i]=’0’の時に、変数zeroをインクリメントするコードを書きました。

Fact[0]からfact[4]までのトレースです。

途中、省略します。

求めた0の個数です。

ここまでのトレースのコードです。

#Nを標準入力で取り込む
N=int(input())


#階乗の計算結果factを1で初期化する
fact=1


#ループを使ってNの階乗N!を変数factに求める
#階乗の計算で乗算する数をmultに格納する
print('<<<forループに入ります。>>>')

for i in range(N):
    print('計算前のfact:'+str(fact))
    mult=N-i
    print('fact×「'+str(mult)+'」を計算する')
    fact*=mult
    print('計算後のfact:【'+str(fact)+'】')
    print('------------------')
    
print('<<<forループを抜けました。>>>')    

#factが膨大な数になり、通常の10で割っていって0の数を求める方法が適用出来ない為、文字列に変換する
fact=str(fact)
print('文字列に変換したfact')
print(fact)

#末尾の'0'を求めるため、文字列を反転する
fact=list(reversed(fact))
print('文字列を反転したfact')
print(fact)

#'0'の数を数える変数zeroを0で初期化する
zero=0

#whileループで文字列factのi番目が'0'というの条件を満たす間、ループを回して'0'の数を数える変数zeroをインクリメントする
print('<<<whileループに入ります。>>>')

i=0  #whileループの場合、ループの変数の初期化も忘れない!!
print('zeroの初期値'+str(zero))
while(fact[i]=='0'):
    print('fact['+str(i)+']=「0」なのでzeroをインクリメントする')
    zero+=1
    print('zero:'+str(zero))
    i+=1 #ループの変数のインクリメントを忘れない!!これを忘れると無限ループになる!!
    print('--------------')

print('<<<whileループを抜けました。>>>')    
    

#zeroを表示
print(zero)

このままでは、出力結果である出力例1に対して冗長なコードが含まれているので、解答以外のprint文をコメントアウトします。


#Nを標準入力で取り込む
N=int(input())


#階乗の計算結果factを1で初期化する
fact=1


#ループを使ってNの階乗N!を変数factに求める
#階乗の計算で乗算する数をmultに格納する
#print('<<<forループに入ります。>>>')

for i in range(N):
    #print('計算前のfact:'+str(fact))
    mult=N-i
    #print('fact×「'+str(mult)+'」を計算する')
    fact*=mult
    #print('計算後のfact:【'+str(fact)+'】')
    #print('------------------')
    
#print('<<<forループを抜けました。>>>')    

#factが膨大な数になり、通常の10で割っていって0の数を求める方法が適用出来ない為、文字列に変換する
fact=str(fact)
#print('文字列に変換したfact')
#print(fact)

#末尾の'0'を求めるため、文字列を反転する
fact=list(reversed(fact))
#print('文字列を反転したfact')
#print(fact)

#'0'の数を数える変数zeroを0で初期化する
zero=0

#whileループで文字列factのi番目が'0'というの条件を満たす間、ループを回して'0'の数を数える変数zeroをインクリメントする
#print('<<<whileループに入ります。>>>')

i=0  #whileループの場合、ループの変数の初期化も忘れない!!
#print('zeroの初期値'+str(zero))
while(fact[i]=='0'):
    #print('fact['+str(i)+']=「0」なのでzeroをインクリメントする')
    zero+=1
    #print('zero:'+str(zero))
    i+=1 #ループの変数のインクリメントを忘れない!!これを忘れると無限ループになる!!
    #print('--------------')

#print('<<<whileループを抜けました。>>>')    
    

#zeroを表示
print(zero)

スッキリするように、コメントアウトした部分を省いたコードです。


#Nを標準入力で取り込む
N=int(input())


#階乗の計算結果factを1で初期化する
fact=1


#ループを使ってNの階乗N!を変数factに求める
#階乗の計算で乗算する数をmultに格納する
for i in range(N):
    mult=N-i
    fact*=mult


#factが膨大な数になり、通常の10で割っていって0の数を求める方法が適用出来ない為、文字列に変換する
fact=str(fact)


#末尾の'0'を求めるため、文字列を反転する
fact=list(reversed(fact))


#'0'の数を数える変数zeroを0で初期化する
zero=0


#whileループで文字列factのi番目が'0'というの条件を満たす間、ループを回して'0'の数を数える変数zeroをインクリメントする
i=0  #whileループの場合、ループの変数の初期化も忘れない!!
while(fact[i]=='0'):
    zero+=1
    i+=1 #ループの変数のインクリメントを忘れない!!これを忘れると無限ループになる!!


#zeroを表示
print(zero)

ioの出力結果です。

■ GASでの解き方 ■

では、同じ問題をGASで解いてみます。
まず、スプレッドシートにこの様に配置しました。

スプレッドシートの緑のセルに階乗を求める整数の100を入力します。
灰色のセルには100!の計算結果を出力します。
黄色いセルには、100の階乗100!の末尾に0が付く個数を出力します。
0の個数は変数zeroに求めます。

また、factを二次元配列としてfact2に追加して、zeroを二次元配列zero2に追加して、それぞれスプレッドシートに出力します。

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

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

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

2:階乗を求める整数N(この例の場合は100)を取得する


3:階乗の計算結果factを1で初期化する


4:100×99×98×97・・・4×3×2×1の掛けていく数を格納するmultを宣言する


5:10で割れる回数tenを0で初期化する


6:5で割れる回数fiveを0で初期化する


7:2で割れる回数twoを0で初期化する


8:末尾に付く0の個数zeroを0で初期化する


9:multが10,5,2それぞれで何回割れるのか数えて変数countに格納するので0で初期化する


10:multを代入する変数tempを宣言する

11:forループで100!を計算する

12:階乗の計算に用いたmultをtempに代入してwhileループに入る

13:10,5,2のいずれかで割れる間にtempを割っていってcountとten,five,twoをインクリメントさせる

14:10,5,2それぞれの割れた回数をログ出力

15:2,5で割れた回数が少ない方と10で割れた回数を合計してzeroに格納する

16:0が付く個数をログ表示

17:factをスプレッドシートに表示する二次元配列fact2を宣言する

18:fact2にfactを二次元配列になるように追加する

19:zeroをスプレッドシートに表示する二次元配列zero2を宣言する

20:zero2にzeroを二次元配列になるように追加する

21:スプレッドシートに出力前のfact2とzero2をログ出力して確認する

22:スプレッドシートの灰色の所に100!と、黄色い所に0の個数をそれぞれ二次元配列として出力する

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

const ss=SpreadsheetApp.getActiveSheet();

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

手順2:階乗を求める整数N(この例の場合は100)を取得する

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

手順3:階乗の計算結果factを1で初期化する

let fact=1;

手順4:100×99×98×97・・・4×3×2×1の掛けていく数を格納するmultを宣言する

let mult;

手順5:10で割れる回数tenを0で初期化する

let ten=0;

手順6:5で割れる回数fiveを0で初期化する

let five=0;

手順7:2で割れる回数twoを0で初期化する

let two=0;

手順8:末尾に付く0の個数zeroを0で初期化する

let zero=0;

手順9:multが10,5,2それぞれで何回割れるのか数えて変数countに格納するので0で初期化する

let count;

手順10:multを代入する変数tempを宣言する

let temp;

手順11から13はループです。
まず、forループで100!を求めます。
100!はとてつもなく大きい数になるので、whileループを使って、末尾の0の数を「掛ける数mult」から求めます。

multの値が変わらないように、multをtempに代入して、10または5または2で割れる間割り算をして行き、それぞれの割れる回数ten,five,twoをインクリメントさせます。

手順11:forループで100!を計算する
手順12:階乗の計算に用いたmultをtempに代入してwhileループに入る
手順13:10,5,2のいずれかで割れる間にtempを割っていってcountとten,five,twoをインクリメントさせる

下の図は、fact=1にまず初めに100を掛ける所です。
forループで階乗の計算をしながら、multを使って10で何回割れるのか求める為に、変数tempを利用しています。

この、for,while部分のコードです。

console.log('<<<forループに入る>>>');

  //forループで100!を計算する
  //階乗の計算に用いたmultをtempに代入してwhileループに入る
  //10,5,2のいずれかで割れる間にtempを割っていってcountとten,five,twoをインクリメントさせる
  for (let i = 0; i < N; i++) {
    console.log(`計算前のfact:${fact}`);
    count = 0;
    mult = N - i;
    console.log(`mult=(N-i):【${mult}】`);

    console.log(`fact:${fact}*「${mult}」を計算`);
    fact *= mult;
    console.log(`計算後のfact:【${fact}】`);

    temp = mult;

    //10,5,2のいずれかで割れる間にtempを割っていってcountとten,five,twoをインクリメントさせる
    while (temp % 10 == 0 || temp % 5 == 0 || temp % 2 == 0) {

      console.log('<<<whileループに入りました。>>>');

      if (temp % 10 == 0) {
        temp /= 10
        count++;
        ten++;
        console.log(`mult:${mult}の時、10で${count}回割れました。`);
      } else if (temp % 5 == 0) {
        temp /= 5
        count++;
        five++;
        console.log(`mult:${mult}の時、5で${count}回割れました。`);
      } else if (temp % 2 == 0) {
        temp /= 2
        count++;
        two++;
        console.log(`mult:${mult}の時、2で${count}回割れました。`);
      }

      console.log('<<<whileループを抜けました。>>>');

    }

    console.log(`現在の計算結果fact:${fact}`);
    console.log('----------------------------');

  }

  console.log('<<<forループを抜けました。>>>');

手順14:10,5,2それぞれの割れた回数をログ出力

//10,5,2それぞれの割れた回数をログ出力
  console.log(`multが10で割れた回数:${ten}回`);
  console.log(`multが5で割れた回数:${five}回`);
  console.log(`multが2で割れた回数:${two}回`);

手順15:2,5で割れた回数が少ない方(two または five)と10で割れた回数(ten)を合計してzeroに格納する。階乗の末尾に何個0が付くかは、「10で割れた回数」と「2×5で割れた回数」の合計になります。
なので、2×5のペアを作るため、twoとfiveの少ない方をtenに足した回数がzeroになります。

//2,5で割れた回数が少ない方と10で割れた回数を合計してzeroに格納する
  if (two < five) {
    zero = ten + two
    console.log(`5で割れた回数よりも2で割れた回数の方が少ないので、\n0が付く個数はzero=ten:${ten}+two:${two}=${zero}です。`);
  } else {
    zero = ten + five;
    console.log(`2で割れた回数よりも5で割れた回数の方が少ないので、\n0が付く個数はzero=ten:${ten}+five:${five}=${zero}です。`);
  }

手順16:0が付く個数をログ表示

console.log(`0は${zero}個付きます。`);

手順17:factをスプレッドシートに表示する二次元配列fact2を宣言する

let fact2=[];

手順18:fact2にfactを二次元配列になるように追加する

fact2.push([fact]);

手順19:zeroをスプレッドシートに表示する二次元配列zero2を宣言する

let zero2=[];

手順20:zero2にzeroを二次元配列になるように追加する

zero2.push([zero]);

手順21:スプレッドシートに出力前のfact2とzero2をログ出力して確認する

console.log(fact2);
console.log(zero2);

手順22:スプレッドシートの灰色の所に100!と、黄色い所に0の個数をそれぞれ二次元配列として出力する

ss.getRange(2,2).setValue(fact);
ss.getRange(3,2).setValue(zero2);

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

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

function loop2no15() {

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

  //階乗を求める整数N(この例の場合は100)を取得する
  const N = ss.getRange(1, 2).getValue();

  //階乗の計算結果factを1で初期化する
  let fact = 1;

  //100×99×98×97・・・4×3×2×1の掛けていく数を格納するmultを宣言する
  let mult;

  //10で割れる回数tenを0で初期化する
  let ten = 0;

  //5で割れる回数fiveを0で初期化する
  let five = 0;

  //2で割れる回数twoを0で初期化する
  let two = 0;

  //末尾に付く0の個数zeroを0で初期化する
  let zero = 0;

  //multが10,5,2それぞれで何回割れるのか数えて変数countに格納するので0で初期化する
  let count;

  //multを代入する変数tempを宣言する
  let temp;

  console.log('<<<forループに入る>>>');

  //forループで100!を計算する
  //階乗の計算に用いたmultをtempに代入してwhileループに入る
  //10,5,2のいずれかで割れる間にtempを割っていってcountとten,five,twoをインクリメントさせる
  for (let i = 0; i < N; i++) {
    console.log(`計算前のfact:${fact}`);
    count = 0;
    mult = N - i;
    console.log(`mult=(N-i):【${mult}】`);

    console.log(`fact:${fact}*「${mult}」を計算`);
    fact *= mult;
    console.log(`計算後のfact:【${fact}】`);

    temp = mult;

    //10,5,2のいずれかで割れる間にtempを割っていってcountとten,five,twoをインクリメントさせる
    while (temp % 10 == 0 || temp % 5 == 0 || temp % 2 == 0) {

      console.log('<<<whileループに入りました。>>>');

      if (temp % 10 == 0) {
        temp /= 10
        count++;
        ten++;
        console.log(`mult:${mult}の時、10で${count}回割れました。`);
      } else if (temp % 5 == 0) {
        temp /= 5
        count++;
        five++;
        console.log(`mult:${mult}の時、5で${count}回割れました。`);
      } else if (temp % 2 == 0) {
        temp /= 2
        count++;
        two++;
        console.log(`mult:${mult}の時、2で${count}回割れました。`);
      }

      console.log('<<<whileループを抜けました。>>>');

    }

    console.log(`現在の計算結果fact:${fact}`);
    console.log('----------------------------');

  }

  console.log('<<<forループを抜けました。>>>');

  //10,5,2それぞれの割れた回数をログ出力
  console.log(`multが10で割れた回数:${ten}回`);
  console.log(`multが5で割れた回数:${five}回`);
  console.log(`multが2で割れた回数:${two}回`);

  //2,5で割れた回数が少ない方と10で割れた回数を合計してzeroに格納する
  if (two < five) {
    zero = ten + two
    console.log(`5で割れた回数よりも2で割れた回数の方が少ないので、\n0が付く個数はzero=ten:${ten}+two:${two}=${zero}です。`);
  } else {
    zero = ten + five;
    console.log(`2で割れた回数よりも5で割れた回数の方が少ないので、\n0が付く個数はzero=ten:${ten}+five:${five}=${zero}です。`);
  }

  //0が付く個数をログ表示
  console.log(`0は${zero}個付きます。`);

  //factをスプレッドシートに表示する二次元配列fact2を宣言する
  let fact2 = [];

  //fact2にfactを二次元配列になるように追加する
  fact2.push([fact]);

  //zeroをスプレッドシートに表示する二次元配列zero2を宣言する
  let zero2 = [];

  //zero2にzeroを二次元配列になるように追加する
  zero2.push([zero]);


  //スプレッドシートに出力前のfact2とzero2をログ出力して確認する
  console.log(fact2);
  console.log(zero2);


  //スプレッドシートの灰色の所に100!と、黄色い所に0の個数をそれぞれ二次元配列として出力する
  ss.getRange(2, 2).setValue(fact);
  ss.getRange(3, 2).setValue(zero2);


}

宜しかったらコピペしてアレンジして見て下さい。
お疲れ様でした、ブレイクタイムフォトはこちらになります。

代々木公園で撮影した紫陽花

■ 参考文献の紹介■

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

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

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

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

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

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

paiza レベルアップ問題集 「STEP: 9 階乗の計算」をPythonとGASで解いてみた

この記事を読むことで、PythonとGASでforループを使って階乗の計算の仕方を学べます。この記事では5!(5の階乗、5×4×3×2×1=120)を扱います。
また、ループの中で変動する値をトレースするコードも付け加えました。

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

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

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

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

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

階乗の計算 (paizaランク D 相当)

問題:
整数 N が与えられます。
N の階乗 N! を計算して出力してください。

この記事では、下記の入力例2の場合を例にして、5!を求めます。
5の階乗は、5×4×3×2×1=120です。

入力例2
5

出力例2
120

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

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

■ Pythonでの解き方 ■

下準備として、paiza.ioにこの様に入力します。
(入力例1をそのままioにコピーしただけ。)

手順として、

1:Nを標準入力で取り込む

2:階乗の計算結果factを1で初期化する


3:ループでfactにfact*=(N-i)を計算する


4:factを表示

で、行います。

まずは、プログラムの各変数の動きを追いやすいように、トレースのio出力結果と、トレースのコードを添えます。
ループの変数iは、0からこの例ですと4まで変動します。

fact=1,i=0の時

fact*=(5-0)
fact=5

fact=5,i=1の時

fact*=(5-1)
fact=20

fact=20,i=2の時

fact*=(5-2)
fact=60

fact=60,i=3の時

fact*=(5-3)
fact=120

fact=120,i=4の時

fact*=(5-4)
fact=120

これで、5!=120が求まりました。
ここまでのトレースのコードを掲載します。

計算結果です。


#標準入力で整数Nを取得する
N=int(input())

#階乗を計算するfactを1で初期化する
fact=1

#ループで階乗の計算をする

print('<<<forループに入ります。>>>')


for i in range(N):
    print('計算前のfactは'+str(fact)+'です。')
    print(str(fact)+'×「'+str(N-i)+'」を計算します。')
    fact*=(N-i)
    print('計算後のfactは【'+str(fact)+'】です。')
    print('----------------------')


print('<<<forループを抜けました。>>>')

print(fact)    

このままでは、出力結果である出力例2に対して冗長なコードが含まれているので、解答以外のprint文をコメントアウトします。

#標準入力で整数Nを取得する
N=int(input())

#階乗を計算するfactを1で初期化する
fact=1

#ループで階乗の計算をする

#print('<<<forループに入ります。>>>')


for i in range(N):
    #print('計算前のfactは'+str(fact)+'です。')
    #print(str(fact)+'×「'+str(N-i)+'」を計算します。')
    fact*=(N-i)
    #print('計算後のfactは【'+str(fact)+'】です。')
    #print('----------------------')


#print('<<<forループを抜けました。>>>')

print(fact)    

スッキリするように、コメントアウトした部分を省いたコードです。

#標準入力で整数Nを取得する
N=int(input())


#階乗を計算するfactを1で初期化する
fact=1


#ループで階乗の計算をする
for i in range(N):
    fact*=(N-i)


print(fact)    

ioの出力結果です。

■ GASでの解き方 ■

では、同じ問題をGASで解いてみます。
まず、スプレッドシートにこの様に配置しました。
このシートの緑色のセルN=5を取得して、5!を計算し、階乗の計算結果を黄色いセルに格納します。

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

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

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

2:スプレッドシートの緑色のセルの整数N(この例では5)を取得する


3:階乗の計算に使用する変数factの初期値を1にする


4:forループで階乗を計算


5:factが計算出来たことをログ出力で確認


6:スプレッドシートに二次元配列として格納する変数fact2を宣言


7:fact2にfactの計算結果を二次元配列になるように追加


8:スプレッドシートに出力前のfact2をログ出力して確認する


9:スプレッドシートの黄色い所に階乗の計算結果を二次元配列として格納したfact2を出力する

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

const ss=SpreadsheetApp.getActiveSheet();

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

手順2:スプレッドシートの緑色のセルの整数N(この例では5)を取得する

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

手順3:階乗の計算に使用する変数factの初期値を1にする

let fact=1;

手順4:forループで階乗を計算

Forループ内をトレースします。

fact=1,i=0の時

fact*=(5-0)
fact=5

fact=5,i=1の時

fact*=(5-1)
fact=20

fact=20,i=2の時

fact*=(5-2)
fact=60

fact=60,i=3の時

fact*=(5-3)
fact=120

fact=120,i=4の時

fact*=(5-4)
fact=120

これで、5!=120が求まりました。
Forループ内のコードを掲載します。

console.log('<<<forループに入ります。>>>');


  //forループで階乗を計算
  for (let i=0;i<N;i++){
    console.log(`計算前のfactは${fact}です。`);
    console.log(`${fact}×「${N-i}」を計算します。`);
    fact*=(N-i);
    console.log(`計算後のfactは【${fact}】です。`);
    console.log('--------------------------------');
  }

  console.log('<<<forループを抜けました。>>>');

手順5:factが計算出来たことをログ出力で確認

console.log(fact);

手順6:スプレッドシートに二次元配列として格納する変数fact2を宣言

let fact2=[];

手順7:fact2にfactの計算結果を二次元配列になるように追加

fact2.push([fact]);

手順8:スプレッドシートに出力前のfact2をログ出力して確認する

console.log(fact2);

手順9:スプレッドシートの黄色い所に階乗の計算結果を二次元配列として格納したfact2を出力する

ss.getRange(2,2).setValue(fact2);

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

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

function loop2no14() {

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

  //スプレッドシートの緑色のセルの整数N(この例では5)を取得する
  const N = ss.getRange(1, 2).getValue();

  //階乗の計算に使用する変数factの初期値を1にする
  let fact = 1;


  console.log('<<<forループに入ります。>>>');


  //forループで階乗を計算
  for (let i = 0; i < N; i++) {
    console.log(`計算前のfactは${fact}です。`);
    console.log(`${fact}×「${N - i}」を計算します。`);
    fact *= (N - i);
    console.log(`計算後のfactは【${fact}】です。`);
    console.log('--------------------------------');
  }

  console.log('<<<forループを抜けました。>>>');


  //factが計算出来たことをログ出力で確認
  console.log(fact);

  //スプレッドシートに二次元配列として格納する変数fact2を宣言
  let fact2 = [];

  //fact2にfactの計算結果を二次元配列になるように追加
  fact2.push([fact]);

  //スプレッドシートに出力前のfact2をログ出力して確認する
  console.log(fact2);

  //スプレッドシートの黄色い所に階乗の計算結果を二次元配列として格納したfact2を出力する
  ss.getRange(2, 2).setValue(fact2);

}

宜しかったらコピペしてアレンジして見て下さい。
お疲れ様でした、ブレイクタイムフォトはこちらになります。

癒しの海、房総半島外房、御宿の海。

■ 参考文献の紹介■

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

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

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

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

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

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

paiza レベルアップ問題集 「STEP: 8 毎日増加するお金」をPythonとGASで解いてみた

この記事を読むことで、PythonとGASでwhileループを使って、変動する値を加算をしていく過程で、変数がどのように変化するのかを学べます。

毎日、所持金A円にA円の10%ずつ加算して行って、何日加算したら目標金額B円を超えるのかを求めます。

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

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

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

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

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

毎日増加するお金 (paizaランク D 相当)

問題:
現在所持金を A 円持っています。
所持金が毎日 10% ずつ増えるとき、何日後に B 円を超えるか出力してください。
また、増加するお金は小数点以下切り捨てで考えることとします。
例として、所持金が 831 円 のとき、10% は 83.1円 ですが、増加するお金は 83 円 です。

この記事では、下記の入力例3の場合を例にして、A円の813円が10%ずつ増えると「何日後にB円の10000円を超えるか」を求めて行きます。

入力例3
813 10000

出力例3
27

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

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

■ Pythonでの解き方 ■

下準備として、paiza.ioにこの様に入力します。
(入力例1をそのままioにコピーしただけ。)

手順として、

1:A,Bを標準入力で取り込む

2:ループの何日目でAの813円がBの10000を超えるかの日数を数える変数dayを0で初期化する


3:whileループでA<=Bの条件を満たす間、ループを回して加算する。dayをインクリメントする


4:dayを表示

で、行います。

まずは、プログラムの各変数の動きを追いやすいように、トレースのio出力結果と、トレースのコードを添えます。

Whileループのトレースをします。
27日間の増加の詳細です。

<1日〜3日目までのトレース>

<4日〜6日目までのトレース>

<7日〜9日目までのトレース>

<10日〜12日目までのトレース>

<13日〜15日目までのトレース>

<16日〜18日目までのトレース>

<19日〜21日目までのトレース>

<22日〜24日目までのトレース>

<25日〜27日目までのトレース>

元手のA円から目標金額B円までかかった日数dayはこちらです。

ここまでのwhileループによるトレースの部分のコードです。

#標準入力で元手の金額A円と基準の金額B円を取得する
A,B=map(int,input().rstrip().split(' '))


#元手A円がB円を超える日数dayを0で初期化する
day=0


#whileループでA<=Bの間、お金を増やす

print('<<<whileループに入る>>>')

while A<=B:
    print('計算前のAの金額:'+str(A)+'円')
    
    #増加するお金
    print('増加するお金は「'+str(int(A/10))+'円」です。')
    
    #お金を増やす
    A+=int(A/10)
    
    print('計算後のAの金額:'+str(A)+'円')
    
    #dayをインクリメント
    day+=1
    print('経過日数【'+str(day)+'】')
    
    print(('---------------------------'))

print('<<<whileループを抜ける>>>')

print(day)    

このままでは、出力結果である出力例3に対して冗長なコードが含まれているので、解答以外のprint文をコメントアウトします。

#標準入力で元手の金額A円と基準の金額B円を取得する
A,B=map(int,input().rstrip().split(' '))


#元手A円がB円を超える日数dayを0で初期化する
day=0


#whileループでA<=Bの間、お金を増やす

#print('<<<whileループに入る>>>')

while A<=B:
    #print('計算前のAの金額:'+str(A)+'円')
    
    #増加するお金
    #print('増加するお金は「'+str(int(A/10))+'円」です。')
    
    #お金を増やす
    A+=int(A/10)
    
    #print('計算後のAの金額:'+str(A)+'円')
    
    #dayをインクリメント
    day+=1
    #print('経過日数【'+str(day)+'】')
    
    #print(('---------------------------'))

#print('<<<whileループを抜ける>>>')

print(day)  

スッキリするように、コメントアウトした部分を省いたコードです。

#標準入力で元手の金額A円と基準の金額B円を取得する
A,B=map(int,input().rstrip().split(' '))


#元手A円がB円を超える日数dayを0で初期化する
day=0


#whileループでA<=Bの間、お金を増やす
while A<=B:
    
    #お金を増やす
    A+=int(A/10)
    
    #dayをインクリメント
    day+=1

print(day)    

ioの出力結果です。

■ GASでの解き方 ■

では、同じ問題をGASで解いてみます。
まず、スプレッドシートにこの様に配置しました。

スプレッドシートの黄色いセルの所に「加算される整数N(=1)、増加する数M(=3)、加算して超える基準値K(=8)」でKを超えるまでに加算した回数を出力します。
Whileループで加算する回数を変数countに格納します。
また、countを二次元配列count2に追加して、スプレッドシートに出力します。

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

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

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

2:整数A,Bを取得する配列arrayを宣言する


3:スプレッドシートの緑色のセルにある金額A円(この例では「813」)と、灰色のセルにある目標金額B円(この例では10000)を2行1列の配列分取得して、arrayに格納する


4:arrayを出力して、各数が配列に格納されていることをログで確認する


5:A=array[0][0]、B=array[1][0]として代入する。この時Aは変数で、Bは定数になる。


6:それぞれの変数、定数が正しく代入されたことをログで確認する


7:Aに10%の金額ずつ足していく日数dayを0で初期化する


8:whileループを使ってAに現在のAの10%ずつ加算する「A+=Math.floor(A/10)」の計算をして、dayをインクリメントする


9:スプレッドシートにdayに格納された日数を二次元配列として格納するday2を宣言する


10:day2に二次元配列になるようにdayを追加


11:スプレッドシートに出力前のday2を出力して確認する


12:スプレッドシートの黄色い所に日数を二次元配列として格納したday2を出力する

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

const ss=SpreadsheetApp.getActiveSheet();

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

手順2:整数A,Bを取得する配列arrayを宣言する

let array=[];

手順3:スプレッドシートの緑色のセルにある金額A円(この例では「813」)と、灰色のセルにある目標金額B円(この例では10000)を2行1列の配列分取得して、arrayに格納する。
下のスプレッドシートより、セルB1つまり(1,2)から2行分を取得するので、getRangeの引数に(1,2,2)と書きます。

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

手順4:arrayを出力して、各数が配列に格納されていることをログで確認する

console.log(array);

手順5:A=array[0][0]、B=array[1][0]として代入する。この時Aは変数で、Bは定数になる。

let A=array[0][0];
const B=array[1][0];

※ Aは10%ずつ加算されていくので値が変わるから変数、それに対して基準値のBは値が変わらないので定数 ※

手順6:それぞれの変数、定数が正しく代入されたことをログで確認する

数値と文字を一緒に出力するときは、[Shiftキー]を押しながら「@」を押して「 ` 」で囲います。

console.log(`現在の所持金A:「${A}円」,目標金額B:「${B}円」`);

手順7:Aに10%の金額ずつ足していく日数dayを0で初期化する

let day=0;

手順8:whileループを使ってAに現在のAの10%ずつ加算する「A+=Math.floor(A/10)」の計算をして、dayをインクリメントする

<1日〜3日目までのトレース>

<4日〜6日目までのトレース>

<7日〜9日目までのトレース>

<10日〜12日目までのトレース>

<13日〜15日目までのトレース>

<16日〜18日目までのトレース>

<19日〜21日目までのトレース>

<22日〜24日目までのトレース>

<25日〜27日目までのトレース>

Whileループの部分のコードです。

  //whileループを使ってAに現在のAの10%ずつ加算する「A+=Math.floor(A/10)」の計算をして、dayをインクリメントする
  
  console.log('<<<ループに入ります。>>>');

  while(A<=B){
    console.log(`加算前の金額A:${A}円`);
    console.log(`加算するAの10%の金額:${Math.floor(A/10)}円`);

    //加算処理
    A+=Math.floor(A/10);

    console.log(`加算後の金額A:${A}円`);

    //日数をインクリメント
    day++;

    console.log(`【${day}】日目`);

    console.log('----------------------');

  }

  console.log('<<<ループを抜けました。>>>');

手順9:スプレッドシートにdayに格納された日数を二次元配列として格納するday2を宣言する

let day2=[];

手順10:day2に二次元配列になるようにdayを追加

day2.push([day]);

手順11:スプレッドシートに出力前のday2を出力して確認する

console.log(day2);

手順12:スプレッドシートの黄色い所に日数を二次元配列として格納したday2を出力する

ss.getRange(5,2).setValue(day2);

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

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

function loop2no13() {

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

  //整数A,Bを取得する配列arrayを宣言する
  let array = [];

  //スプレッドシートの緑色のセルにある金額A円(この例では「813」)と、灰色のセルにある目標金額B円(この例では10000)を2行1列の配列分取得して、arrayに格納する
  array = ss.getRange(1, 2, 2).getValues();

  //arrayを出力して、各数が配列に格納されていることをログで確認する
  console.log(array);

  //A=array[0][0]、B=array[1][0]として代入する。この時Aは変数で、Bは定数になる。
  let A = array[0][0];
  const B = array[1][0];

  //それぞれの変数、定数が正しく代入されたことをログで確認する
  console.log(`現在の所持金A:「${A}円」,目標金額B:「${B}円」`);

  //Aに10%の金額ずつ足していく日数dayを0で初期化する
  let day = 0;

  //whileループを使ってAに現在のAの10%ずつ加算する「A+=Math.floor(A/10)」の計算をして、dayをインクリメントする

  console.log('<<<ループに入ります。>>>');

  while (A <= B) {
    console.log(`加算前の金額A:${A}円`);
    console.log(`加算するAの10%の金額:${Math.floor(A / 10)}円`);

    //加算処理
    A += Math.floor(A / 10);

    console.log(`加算後の金額A:${A}円`);

    //日数をインクリメント
    day++;

    console.log(`【${day}】日目`);

    console.log('----------------------');

  }

  console.log('<<<ループを抜けました。>>>');

  //スプレッドシートにdayに格納された日数を二次元配列として格納するday2を宣言する
  let day2 = [];

  //day2に二次元配列になるようにdayを追加
  day2.push([day]);


  //スプレッドシートに出力前のday2を出力して確認する
  console.log(day2);

  //スプレッドシートの黄色い所に日数を二次元配列として格納したday2を出力する
  ss.getRange(5, 2).setValue(day2);

}

宜しかったらコピペしてアレンジして見て下さい。
お疲れ様でした、ブレイクタイムフォトはこちらになります。

お食事中の方、ごめんなさい、浅草で有名な「うんこビル」です。

■ 参考文献の紹介■

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

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

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

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

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

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

paiza レベルアップ問題集 「STEP: 7 N が M ずつ増えたときにいつ K を越える?」をPythonとGASで解いてみた

この記事を読むことで、PythonとGASでwhileループを使って加算をしていく過程で、変数がどのように変化するのかを学べます。
整数NにMずつ加算して行って、何回加算したらKを超えるかを求めます。

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

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

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

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

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

N が M ずつ増えたときにいつ K を越える? (paizaランク D 相当)

問題:
整数 N, M, K が与えられます。
N が M ずつ増えるとき、何回目に K を越えるか出力してください。

この記事では、下記の入力例3の場合を例にして、N=1がM=3ずつ増えると「いつK=8を超えるか」を求めて行きます。

入力例3
1 3 8

出力例3
3

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

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

■ Pythonでの解き方 ■

下準備として、paiza.ioにこの様に入力します。
(入力例1をそのままioにコピーしただけ。)

手順として、

1:N,M,Kを標準入力で取り込む

2:ループの何回目の足し算でNがKを超えるかを数える変数countを0で初期化する


3:whileループでN<=Kの条件を満たす間、ループを回して加算する。countをインクリメントする

4:countを表示

で、行います。

まずは、プログラムの各変数の動きを追いやすいように、トレースのio出力結果と、トレースのコードを添えます。

Whileループのトレースをします。

1回目の加算

2回目の除算

3回目の除算

ここまでのwhileループによるトレースの部分のコードです。

#N,M,Kを標準入力で取り込む
N,M,K=map(int,input().rstrip().split(' '))

#ループの何回目の足し算でNがKを超えるかを数える変数countを0で初期化する
count=0


#whileループでN<=Kの条件を満たす間、ループを回して加算する。countをインクリメントする。

print('<<<ループに入る>>>')

while N<=K:
    print('計算前のNの値:「'+str(N)+'」')
    print(str(N)+'に'+str(M)+'を加算\n')
    #ここで、NにMを加算する
    N+=M
    print('計算後のNの値:「'+str(N)+'」')
    if N<=K:
        print('K:'+str(K)+'まで'+str(K-N)+'足りない')
    else:
        print('K:'+str(K)+'に対してN:'+str(N)+'で、Kを超えた!!')
    count+=1
    print('加算回数【'+str(count)+'】回')
    print('-----------------------')


print('<<<ループを抜けた>>>')

#countを表示
print(count)

このままでは、出力結果である出力例3に対して冗長なコードが含まれているので、解答以外のprint文をコメントアウトします。

#N,M,Kを標準入力で取り込む
N,M,K=map(int,input().rstrip().split(' '))

#ループの何回目の足し算でNがKを超えるかを数える変数countを0で初期化する
count=0


#whileループでN<=Kの条件を満たす間、ループを回して加算する。countをインクリメントする。

#print('<<<ループに入る>>>')

while N<=K:
    #print('計算前のNの値:「'+str(N)+'」')
    #print(str(N)+'に'+str(M)+'を加算\n')
    #ここで、NにMを加算する
    N+=M
    #print('計算後のNの値:「'+str(N)+'」')
    #if N<=K:
        #print('K:'+str(K)+'まで'+str(K-N)+'足りない')
    #else:
        #print('K:'+str(K)+'に対してN:'+str(N)+'で、Kを超えた!!')
    count+=1
    #print('加算回数【'+str(count)+'】回')
    #print('-----------------------')


#print('<<<ループを抜けた>>>')

#countを表示
print(count)

スッキリするように、コメントアウトした部分を省いたコードです。

#N,M,Kを標準入力で取り込む
N,M,K=map(int,input().rstrip().split(' '))


#ループの何回目の足し算でNがKを超えるかを数える変数countを0で初期化する。countをインクリメントする。
count=0


#whileループでN<=Kの条件を満たす間、ループを回して加算する
while N<=K:
    
    #ここで、NにMを加算する
    N+=M
    count+=1
    
#countを表示
print(count)

ioの出力結果です。

■ GASでの解き方 ■

では、同じ問題をGASで解いてみます。
まず、スプレッドシートにこの様に配置しました。

「加算される整数N(=緑のセル「1」)、増加する数M(=灰色のセル「3」)、加算して超える基準値K(=ピンクのセル「8」)」でKを超えるまでに加算した回数をスプレッドシートの黄色いセルの所に出力します。

Whileループで加算する回数を変数countに格納します。
また、countを二次元配列count2に追加して、スプレッドシートに出力します。

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

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

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

2:整数N,M,Kを取得する配列arrayを宣言する


3:スプレッドシートの緑色のセルにある整数N(この例では「1」)と、灰色のセルにある、加算していく整数M(この例では「3」)と、ピンク色のセルにある加算によって超える基準値の整数K(この例では「8」)を3行1列の配列arrayに取得する


4:arrayを出力して、各数が配列に格納されていることをログで確認する


5:N=array[0][0]、M=array[1][0]、K=array[2][0]として代入する。この時Nのみ変数で、M,Kは定数になる。


6:それぞれの変数、定数が正しく代入されたことをログで確認する


7:NにMを足していく回数countを0で初期化する


8:whileループを使ってNにMずつ加算する(N+=Mを計算)して、countをインクリメントする


9:countを表示する


10:スプレッドシートにcountに格納された加算回数を二次元配列として格納するcount2を宣言する


11:count2に二次元配列としてcountを追加


12:スプレッドシートに出力前のcount2を出力して確認する


13:スプレッドシートの黄色い所に加算回数を二次元配列として格納したcount2を出力する

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

const ss=SpreadsheetApp.getActiveSheet();

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

手順2:整数N,M,Kを取得する配列arrayを宣言する

let array=[];

手順3:スプレッドシートの緑色のセルにある整数N(この例では「1」)と、灰色のセルにある、加算していく整数M(この例では「3」)と、ピンク色のセルにある加算によって超える基準値の整数K(この例では「8」)を3行1列の配列arrayに取得する

スプレッドシートのセルB1は1行目の2列目なので(1,2)と書き、そこから3行取得するので、引数に3も加えます。

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

手順4:arrayを出力して、各数が配列に格納されていることを確認する

console.log(array);

手順5:N=array[0][0]、M=array[1][0]、K=array[2][0]として代入する。この時Nのみ変数で、M,Kは定数になる。

let N=array[0][0];
const M=array[1][0];
const K=array[2][0];

※ NはMを加えていくので値が変わるから変数、それに対してMや基準値のKは値が変わらないので定数 ※

手順6:各変数・定数が格納されたことを確認する

数値と文字を一緒に出力するときは、[Shiftキー]を押しながら「@」を押して「 ` 」で囲います。

console.log(`N:${N},M:${M},K:${K}`);

手順7:NにMを足していく回数countを0で初期化する

let count=0;

手順8:whileループを使ってNにMずつ加算する(N+=Mを計算)して、countをインクリメントする

1回目の加算

2回目の加算

3回目の加算

Whileループの部分のコードです。

  //whileループを使って余りを配列に格納する
  console.log('<<<whileループに入りました>>>');


  while (N >= 1) {
    console.log(`計算前のNの値:${N}`);
    console.log(`計算前の配列array:[${array}]`);
    console.log(`配列に追加する余り【${N % M}】`);

    //配列に追加
    array.push(N % M);

    //割り算の実行
    N /= M;

    //Nを整数にする
    N = Math.floor(N);

    console.log(`計算後のNの値:${N}`);
    console.log(`計算後の配列array:[${array}]`);

    console.log('------------------------');
  }

  console.log('<<<whileループを抜けました。>>>');

手順9:加算回数countを表示

console.log(count);

手順10:スプレッドシートにcountに格納された加算回数を二次元配列として格納するcount2を宣言する

let count2=[];

手順11:count2に二次元配列としてcountを追加

count2.push([count]);

手順12:スプレッドシートに出力前のcount2を出力して確認する

console.log(count2);

手順13:スプレッドシートの黄色い所に加算回数を二次元配列として格納したcount2を出力する

ss.getRange(6,2).setValue(count2);

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

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

function loop2no12() {

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

  //整数N,M,Kを取得する配列arrayを宣言する
  let array = [];

  //スプレッドシートの緑色のセルにある整数N(この例では「1」)と、灰色のセルにある、加算していく整数M(この例では「3」)と、ピンク色のセルにある加算によって超える基準値の整数K(この例では「8」)を3行1列の配列arrayに取得する
  array = ss.getRange(1, 2, 3).getValues();

  //arrayを出力して、各数が配列に格納されていることを確認する
  console.log(array);

  //N=array[0][0]、M=array[1][0]、K=array[2][0]として代入する。この時Nのみ変数で、M,Kは定数になる。
  let N = array[0][0];
  const M = array[1][0];
  const K = array[2][0];

  //各変数・定数が格納されたことを確認する
  console.log(`N:${N},M:${M},K:${K}`);

  //NにMを足していく回数countを0で初期化する
  let count = 0;

  //whileループを使ってNにMずつ加算する(N+=Mを計算)して、countをインクリメントする

  console.log('<<<whileループに入る>>>');

  while (N <= K) {
    console.log(`加算前のN:「${N}」`);
    console.log(`NにM=${M}を加算\n`);

    //加算処理とcountのインクリメント
    N += M;
    count++;

    console.log(`加算後のN:「${N}」`);
    console.log(`加算回数【${count}】回`);

    if (N <= K) {
      console.log(`N=${N}はK=${K}まで「${K - N}」足りない`);
    } else {
      console.log(`N=${N}はK=${K}を超えた!!`);
    }

    console.log('-------------------------');

  }

  console.log('<<<whileループを抜けた>>>');

  //countを表示する
  console.log(count);

  //スプレッドシートにcountに格納された加算回数を二次元配列として格納するcount2を宣言する
  let count2 = [];

  //count2に二次元配列としてcountを追加
  count2.push([count]);

  //スプレッドシートに出力前のcount2を出力して確認する
  console.log(count2);

  //スプレッドシートの黄色い所に加算回数を二次元配列として格納したcount2を出力する
  ss.getRange(6, 2).setValue(count2);

}

宜しかったらコピペしてアレンジして見て下さい。
お疲れ様でした、ブレイクタイムフォトはこちらになります。

横浜ランドマークタワーからの絶景!!
大観覧車の赤と青の自然な感じのコントラストに中央が黄金色なのも、また素敵!!

■ 参考文献の紹介■

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

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

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

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

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

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

GASで「ねこあつめ」のコードにドキュメンテーションコメントを追加する「ねこあつめシリーズその16(最終回)」

この記事では、GAS(Google Apps Script)で「ねこあつめ」をChatworkに送信する為に今まで書いてきたコードに、ドキュメンテーションコメントを追加します。

お世話になった記事は、いつも隣にITのお仕事さん

【初心者向けGAS】Google Apps Scriptのドキュメンテーションコメントの書き方

です。

今回の内容に入る前に、前回の復習をします。
前回はスプレッドシートの猫ちゃんの「なまえ」〜「とくちょう」をChatworkに送る時にメッセージを装飾しました。

Chatworkに送るスプレッドシートです。

実際に送った画像です。

前回のコードです。

//メインの関数でAmazonにDVDの注文をする
function myFunction() {
  const ss = SpreadsheetApp.getActiveSheet();
  let lastRow = ss.getLastRow();//最終行を取得
  const token=PropertiesService.getScriptProperties().getProperty('CW_TOKEN');//←ここを追加

  for (let i = 2; i <= lastRow; i++) {

    //もしもD列の「済」が空白だったらA列の「なまえ」を出力してD列を「済」にする
    if (!ss.getRange(i, 4).getValue()) {
      let cat=ss.getRange(i,1,1,3).getValues();//←配列catで一気に1行3列分のデータを取得する ※getValue[s]でsが付く

      //AmazonがDVDの注文を受け取る
      let body='[info]';  //←ここで、囲い枠線で装飾する
      body+=cat[0][0]+'[hr]';//←A列:猫ちゃんの「なまえ」に水平線を入れる
      body+=cat[0][1]+'\n';//B列:猫ちゃんの「しゅるい」
      body+='('+cat[0][2]+')[/info]';//←C列:猫ちゃんの「とくちょう」を送ったら囲い枠線を閉じる
      
      //ここでAmazonが宅配業者みたいなsendMessage関数にDVDの配達を依頼する
      sendMessage(token,body);
      ss.getRange(i, 4).setValue('済');

      //もしも最終行以上になったらセル範囲を消去する
      if (i >= lastRow) {
        ss.getRange(2, 4, lastRow - 1).clearContent();
      }
      break;
    }
  }
}

//宅配業者のようなsendMessage関数がAmazonからDVDを受け取って、配達を行う
function sendMessage(token,body){
  const cw=ChatWorkClient.factory({token:token}); //←APIトークンの所をtokenに置き換える
  cw.sendMessageToMyChat(body);
}

今回の内容に入る前に、ねこあつめ画像で癒されます。

雪の日のねこあつめ

さて、今回の内容に入ります。

今まで作ってきたコードの関数を、後で見返したり、誰かにコードを見てもらう時に分かりやすくする為に、ドキュメンテーションコメントという、関数を説明する為のコメントを書いて行きます。

ドキュメンテーションコメントは「/」で始まって「*/」で終わります。

引数を@param、戻り値を@returnとして、型を指定します。
今回のコードの32行目〜38行目までドキュメンテーションコメントが入っています。

//メインの関数でAmazonにDVDの注文をする
function myFunction() {
  const ss = SpreadsheetApp.getActiveSheet();
  let lastRow = ss.getLastRow();//最終行を取得
  const token=PropertiesService.getScriptProperties().getProperty('CW_TOKEN');//←ここを追加

  for (let i = 2; i <= lastRow; i++) {

    //もしもD列の「済」が空白だったらA列の「なまえ」を出力してD列を「済」にする
    if (!ss.getRange(i, 4).getValue()) {
      let cat=ss.getRange(i,1,1,3).getValues();//←配列catで一気に1行3列分のデータを取得する ※getValue[s]でsが付く

      //AmazonがDVDの注文を受け取る
      let body='[info]';  //ここで、囲い枠線で装飾する
      body+=cat[0][0]+'[hr]';//A列:猫ちゃんの「なまえ」に水平線を入れる
      body+=cat[0][1]+'\n';//B列:猫ちゃんの「しゅるい」
      body+='('+cat[0][2]+')[/info]';//C列:猫ちゃんの「とくちょう」を送ったら囲い枠線を閉じる
      
      //ここでAmazonが宅配業者みたいなsendMessage関数にDVDの配達を依頼する
      sendMessage(token,body);
      ss.getRange(i, 4).setValue('済');

      //もしも最終行以上になったらセル範囲を消去する
      if (i >= lastRow) {
        ss.getRange(2, 4, lastRow - 1).clearContent();
      }
      break;
    }
  }
}

/**
 * 
 * チャットワークのマイチャットにスプレッドシートの「ねこあつめ」のメッセージを送信する
 * 
 * @param{string} token - チャットワークAPIトークン
 * @param{string} body - スプレッドシートのチャットワークに送信するメッセージ本文
 */

//宅配業者のようなsendMessage関数がAmazonからDVDを受け取って、配達を行う
function sendMessage(token,body){
  const cw=ChatWorkClient.factory({token:token}); //←APIトークンの所をtokenに置き換える
  cw.sendMessageToMyChat(body);
}

今まで通り送れました。因みに今日は大晦日です。

ご精読ありがとうございました。

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

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

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

GASサンプル集に戻る
メインメニューに戻る
これからプログラミングを始める方へ
基本情報技術者へ
自己紹介

←前に戻るにゃん

paiza レベルアップ問題集 「STEP: 6 10 進数から M 進数に変換」をPythonとGASで解いてみた

この記事を読むことで、PythonとGASで10進数から任意の進数(M進数)に基数変換するコードの書き方を学べます。
whileループでMで割った余りをリスト(配列)に格納し、Pythonではスライスを使ってForループでリストの逆順から表示させます。

別解として2進数に変換した結果を数値に格納するコードも記述しました。
GASではこの別解に基づいてコードを書いています。

基本的なループの書き方にスライスを使った書き方、剰余演算子、リスト(配列の追加)など、プログラミングの基幹となる文法の習得を強化できます。

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

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

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

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

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

10 進数から M 進数に変換 (paizaランク C 相当)

問題:
10 進数で表された整数 N, M が与えられます。
N を M 進数に変換して出力してください。

この記事では、下記の入力例2の場合に、10進数N=10と基数変換するM進数M=8が与えられた時に、8進数でどのような計算結果になるのかを求めて行きます。

入力例2
10 8

出力例2
12

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

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

■ Pythonでの解き方 ■

下準備として、paiza.ioにこの様に入力します。
(入力例1をそのままioにコピーしただけ。)

手順として、

1:10進数の数値N=10とM進数のM=8を取得する

2:余りを格納する整数arrayを宣言する


3:whileループでN>=1の間、Mで割り続けて余りをarrayに格納する


4:Forループでスライスを使ってarrayを逆順に取り出す

で、行います。

まずは、プログラムの各変数の動きを追いやすいように、トレースのio出力結果と、トレースのコードを添えます。

10進数の10を8進数に変換すると12になり、計算過程はこちらの画像をご覧下さい。

この計算をwhileループを使って行います。
では、Whileループのトレースをします。

1回目の除算

2回目の除算

以上を踏まえて、トレースの部分を表示したコードを掲載します。

#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))

#余りを格納するリストを宣言
array=[]


#NがM以上の場合に除算を繰り返して余りをリストに格納する

print('<<<ループに入る>>>')

while N>=1:
    print('除算実行前のNの値:'+str(N))
    print('除算実行前のリストarray:'+str(array))
    
    #NをMで除算して、余りをarrayに格納する
    array.append(N%M)
    #リストに格納する余り
    print('リストに追加した余り【'+str(N%M)+'】')
    #除算してNを更新する
    N/=M
    #Nを整数にする
    N=int(N)
    print('除算実行後のNの値:'+str(N))
    print('除算実行後のリストarray:'+str(array))
    
    print('-----------------------')
    

print('<<<ループを抜けた>>>')


#リストを表示
print(array)
    
#リストを逆順から取り出す
for num in array[::-1]:
    print(num,end="")

print()    

このままでは、出力結果である出力例3に対して冗長なコードが含まれているので、解答以外のprint文をコメントアウトします。

#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))

#余りを格納するリストを宣言
array=[]


#NがM以上の場合に除算を繰り返して余りをリストに格納する

#print('<<<ループに入る>>>')

while N>=1:
    #print('除算実行前のNの値:'+str(N))
    #print('除算実行前のリストarray:'+str(array))
    
    #NをMで除算して、余りをarrayに格納する
    array.append(N%M)
    #リストに格納する余り
    #print('リストに追加した余り【'+str(N%M)+'】')
    #除算してNを更新する
    N/=M
    #Nを整数にする
    N=int(N)
    #print('除算実行後のNの値:'+str(N))
    #print('除算実行後のリストarray:'+str(array))
    
    #print('-----------------------')
    

#print('<<<ループを抜けた>>>')


#リストを表示
#print(array)
    
#リストを逆順から取り出す
for num in array[::-1]:
    print(num,end="")

print()  

更に、コードがスッキリするように、コメントアウトした部分を省いたコードです。

#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))

#余りを格納するリストを宣言
array=[]


#NがM以上の場合に除算を繰り返して余りをリストに格納する

while N>=1:
    #NをMで除算して、余りをarrayに格納する
    array.append(N%M)
    #除算してNを更新する
    N/=M
    #Nを整数にする
    N=int(N)


#リストを逆順から取り出す
for num in array[::-1]:
    print(num,end="")

print()  

ioの出力結果です。

上の書き方ではスライスを使ってリストをForループで逆から取り出していましたが、リストを反転させて、[1,2]を12と表記させる方法のコードを掲載します。

別解のコードでは、Forループのトレースと、コメントアウトをしたコード、コメントアウトを取り除いたコードを掲載します。

#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))

#余りを格納するリストを宣言
array=[]


#NがM以上の場合に除算を繰り返して余りをリストに格納する

while N>=1:
    #NをMで除算して、余りをarrayに格納する
    array.append(N%M)
    #除算してNを更新する
    N/=M
    #Nを整数にする
    N=int(N)

#リストを反転させる
print(array)
array=list(reversed(array))
print(array)


#8進数を格納する変数ansを0で初期化
ans=0

print()

#リストの数値を元に計算結果をansに格納

print('<<<Forループに入る>>>')

for num in array:
    print('計算前のansの値:'+str(ans))
    ans*=10
    print('10倍したansの値:'+str(ans))
    print(str(ans)+'に'+str(num)+'を加える')
    ans+=num
    print('計算後のansの値'+str(ans))
    print('-----------------')

print('<<<Forループを抜けた>>>')

print()

print(ans)

For文に入る前に、リストを反転させます。

では、For文のループでの変数の動きを見て行きます。

1回目のansの計算

2回目のansの計算

このコードを出力形式に合わせてコメントアウトしたコードです。

#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))

#余りを格納するリストを宣言
array=[]


#NがM以上の場合に除算を繰り返して余りをリストに格納する

while N>=1:
    #NをMで除算して、余りをarrayに格納する
    array.append(N%M)
    #除算してNを更新する
    N/=M
    #Nを整数にする
    N=int(N)

#リストを反転させる
#print(array)
array=list(reversed(array))
#print(array)


#8進数を格納する変数ansを0で初期化
ans=0

#print()

#リストの数値を元に計算結果をansに格納

#print('<<<Forループに入る>>>')

for num in array:
    #print('計算前のansの値:'+str(ans))
    ans*=10
    #print('10倍したansの値:'+str(ans))
    #print(str(ans)+'に'+str(num)+'を加える')
    ans+=num
    #print('計算後のansの値'+str(ans))
    #print('-----------------')

#print('<<<Forループを抜けた>>>')

#print()

print(ans)

更に、コメント部分を取り除いた、スッキリとしたコードです。

#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))

#余りを格納するリストを宣言
array=[]


#NがM以上の場合に除算を繰り返して余りをリストに格納する

while N>=1:
    #NをMで除算して、余りをarrayに格納する
    array.append(N%M)
    #除算してNを更新する
    N/=M
    #Nを整数にする
    N=int(N)

#リストを反転させる
array=list(reversed(array))

#8進数を格納する変数ansを0で初期化
ans=0

for num in array:
    ans*=10
    ans+=num
    
print(ans)

別解でも無事正解しました。

■ GASでの解き方 ■

では、同じ問題をGASで解いてみます。
まず、スプレッドシートにこの様に配置しました。

スプレッドシートの黄色いセルの所に「10進数N(=10)をM(=8)進数に基数変換をした結果12」を出力します。

基数変換の計算結果はansに格納します。
また、ansを二次元配列ans2に追加して、スプレッドシートに出力します。

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

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

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

2:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する


3:スプレッドシートの灰色のセルからM進数のM(この例では「8」)を取得する


4:8で割った余りを格納する配列を宣言する


5:whileループを使って余りを配列に格納する


6:配列を表示


7:配列を反転させる


8:反転した配列を表示


9:M進数を変数ansに格納する為、ansを0で初期化する


10:Forループで8進数を計算する


11:ansを表示


12:スプレッドシートに格納する二次元配列ans2を宣言


13:ansをans2に二次元配列として格納


14:スプレッドシートに出力前にans2を出力して確認する


15:スプレッドシートの黄色い所に8進数に基数変換した結果を格納する

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

const ss=SpreadsheetApp.getActiveSheet();

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

手順2:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する

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

※Nを割っていくので、Nの値が変わる、すなわち変数なので定数のconstではなく変数のletで宣言をします※

手順3:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する

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

手順4:2で割った余りを格納する配列を宣言する

let array=[]

手順5:whileループを使って余りを配列に格納する

1回目の除算

2回目の除算

whileループの部分のコードです。

//whileループを使って余りを配列に格納する
  console.log('<<<whileループに入りました>>>');
  

  while(N>=1){
    console.log(`計算前のNの値:${N}`);
    console.log(`計算前の配列array:[${array}]`);
    console.log(`配列に追加する余り【${N%M}】`);

    //配列に追加
    array.push(N%M);

    //割り算の実行
    N/=M;

    //Nを整数にする
    N=Math.floor(N);

    console.log(`計算後のNの値:${N}`);
    console.log(`計算後の配列array:[${array}]`);

    console.log('------------------------');
  }

  console.log('<<<whileループを抜けました。>>>');

手順6:配列を表示

console.log(array);

手順7:配列を反転させる

array=array.reverse();

手順8:反転した配列を表示

console.log(array);

配列を反転させる前と後の画像です。

手順9:2進数を変数ansに格納する為、ansを0で初期化する

let ans=0;

手順10:Forループでリストから2進数に基数変換する

1回目のansの計算

2回目のansの計算

Forループのコードです。

//Forループで8進数を計算する
console.log('<<<Forループに入りました>>>');

for(let i=0;i<=array.length-1;i++){
  
  //配列の値をansに計算する
  console.log(`計算前のansの値:${ans}`);
  ans*=10;
  console.log(`ansを10倍にした値:${ans}`);
  ans+=array[i];
  console.log(`計算後のansの値:${ans}`);

  console.log('------------------------');

}

console.log('<<<Forループを抜けました。>>>');

手順11:ansを表示

console.log(ans);

手順12:スプレッドシートに格納する二次元配列ans2を宣言

let ans2=[];

手順13:ansをans2に二次元配列として格納

ans2.push([ans]);

手順14:スプレッドシートに出力前にans2を出力して確認する

console.log(ans2);

手順15:スプレッドシートの黄色い所に8進数に基数変換した結果を格納する

ss.getRange(3,2).setValue(ans2);

実行した後のスプレッドシートです。

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

function loop2no11() {

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

  //スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する
  let N = ss.getRange(1, 2).getValue();

  //スプレッドシートの灰色のセルからM進数のM(この例では「8」)を取得する
  const M = ss.getRange(2, 2).getValue();

  //8で割った余りを格納する配列を宣言する
  let array = [];


  //whileループを使って余りを配列に格納する
  console.log('<<<whileループに入りました>>>');


  while (N >= 1) {
    console.log(`計算前のNの値:${N}`);
    console.log(`計算前の配列array:[${array}]`);
    console.log(`配列に追加する余り【${N % M}】`);

    //配列に追加
    array.push(N % M);

    //割り算の実行
    N /= M;

    //Nを整数にする
    N = Math.floor(N);

    console.log(`計算後のNの値:${N}`);
    console.log(`計算後の配列array:[${array}]`);

    console.log('------------------------');
  }

  console.log('<<<whileループを抜けました。>>>');


  //配列を表示
  console.log(array);

  //配列を反転させる
  array = array.reverse();

  //反転した配列を表示
  console.log(array);

  //M進数を変数ansに格納する為、ansを0で初期化する
  let ans = 0;

  //Forループで8進数を計算する
  console.log('<<<Forループに入りました>>>');

  for (let i = 0; i <= array.length - 1; i++) {

    //配列の値をansに計算する
    console.log(`計算前のansの値:${ans}`);
    ans *= 10;
    console.log(`ansを10倍にした値:${ans}`);
    ans += array[i];
    console.log(`計算後のansの値:${ans}`);

    console.log('------------------------');

  }

  console.log('<<<Forループを抜けました。>>>');

  //ansを表示
  console.log(ans);

  //スプレッドシートに格納する二次元配列ans2を宣言
  let ans2 = [];

  //ansをans2に二次元配列として格納
  ans2.push([ans]);

  //スプレッドシートに出力前にans2を出力して確認する
  console.log(ans2);

  //スプレッドシートの黄色い所に8進数に基数変換した結果を格納する
  ss.getRange(4, 2).setValue(ans2);

}

宜しかったらコピペしてアレンジして見て下さい。
お疲れ様でした、ブレイクタイムフォトはこちらになります。

神奈川県川崎市、工場地帯の工場萌え写真。

■ 参考文献の紹介■

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

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

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

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

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

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

GASで「ねこあつめ」をChatworkにメッセージを装飾して送る「ねこあつめシリーズその15」

この記事では、GAS(Google Apps Script)で「ねこあつめ」をChatworkに送信する時に、メッセージを装飾して送る方法を掲載しています。

お世話になった記事は、いつも隣にITのお仕事さんの

【初心者向けGAS】チャットワークのメッセージ記法でBot送信するメッセージを装飾する方法

です。

今回の内容に入る前に、前回の復習をします。
前回はスプレッドシートの猫ちゃんの「なまえ」〜「とくちょう」までを配列として取得して、Chatworkに送ることによって、スプレッドシートのアクセス回数を格段に減らせました。

こちらのスプレッドシートです。

このスプレッドシートを元に、Chatworkに出力した画像とコードです。

//メインの関数でAmazonにDVDの注文をする
function myFunction() {
  const ss = SpreadsheetApp.getActiveSheet();
  let lastRow = ss.getLastRow();//最終行を取得
  const token=PropertiesService.getScriptProperties().getProperty('CW_TOKEN');//←ここを追加

  for (let i = 2; i <= lastRow; i++) {

    //もしもD列の「済」が空白だったらA列の「なまえ」を出力してD列を「済」にする
    if (!ss.getRange(i, 4).getValue()) {
      let cat=ss.getRange(i,1,1,3).getValues();//←配列catで一気に1行3列分のデータを取得する ※getValue[s]でsが付く

      //AmazonがDVDの注文を受け取る
      let body="";  //←ここで、bodyにA列、B列、C列のデータを追加していくので、bodyをletで変数として宣言
      body+=cat[0][0]+'\n';//A列:猫ちゃんの「なまえ」
      body+=cat[0][1]+'\n';//B列:猫ちゃんの「しゅるい」
      body+=cat[0][2]+'\n';//C列:猫ちゃんの「とくちょう」
      
      //ここでAmazonが宅配業者みたいなsendMessage関数にDVDの配達を依頼する
      sendMessage(token,body);
      ss.getRange(i, 4).setValue('済');

      //もしも最終行以上になったらセル範囲を消去する
      if (i >= lastRow) {
        ss.getRange(2, 4, lastRow - 1).clearContent();
      }
      break;
    }
  }
}

//宅配業者のようなsendMessage関数がAmazonからDVDを受け取って、配達を行う
function sendMessage(token,body){
  const cw=ChatWorkClient.factory({token:token}); //←APIトークンの所をtokenに置き換える
  cw.sendMessageToMyChat(body);
}

今回の内容に入る前に、ねこあつめ画像で癒されます。

さて、今回の内容に入ります。

Chatworkにメッセージを送る際にタグを使って、メッセージを装飾します。
角カッコを使った、「メッセージ記法」という書き方を使ってコードを書いて行きます。

ここでは、メッセージを[info]というタグを使って囲い始め、水平の線を[HR]というタグで挿入して、丸カッコを使って体裁を整えて、[/info]で閉じます。

タグは、シングルクォーテーションで囲います。
「/」は、バックスラッシュではなく、普通のスラッシュです。

下記のコードで、14行目から17行目までにタグを入れてコメントを付けました。

//メインの関数でAmazonにDVDの注文をする
function myFunction() {
  const ss = SpreadsheetApp.getActiveSheet();
  let lastRow = ss.getLastRow();//最終行を取得
  const token=PropertiesService.getScriptProperties().getProperty('CW_TOKEN');//←ここを追加

  for (let i = 2; i <= lastRow; i++) {

    //もしもD列の「済」が空白だったらA列の「なまえ」を出力してD列を「済」にする
    if (!ss.getRange(i, 4).getValue()) {
      let cat=ss.getRange(i,1,1,3).getValues();//←配列catで一気に1行3列分のデータを取得する ※getValue[s]でsが付く

      //AmazonがDVDの注文を受け取る
      let body='[info]';  //←ここで、囲い枠線で装飾する
      body+=cat[0][0]+'[hr]';//←A列:猫ちゃんの「なまえ」に水平線を入れる
      body+=cat[0][1]+'\n';//B列:猫ちゃんの「しゅるい」
      body+='('+cat[0][2]+')[/info]';//←C列:猫ちゃんの「とくちょう」を送ったら囲い枠線を閉じる
      
      //ここでAmazonが宅配業者みたいなsendMessage関数にDVDの配達を依頼する
      sendMessage(token,body);
      ss.getRange(i, 4).setValue('済');

      //もしも最終行以上になったらセル範囲を消去する
      if (i >= lastRow) {
        ss.getRange(2, 4, lastRow - 1).clearContent();
      }
      break;
    }
  }
}

//宅配業者のようなsendMessage関数がAmazonからDVDを受け取って、配達を行う
function sendMessage(token,body){
  const cw=ChatWorkClient.factory({token:token}); //←APIトークンの所をtokenに置き換える
  cw.sendMessageToMyChat(body);
}

まずは1匹目の猫ちゃん、「ヘキサにゃん」

1匹目の「ヘキサにゃん」が「済」になりました。
他のコ達も送ってみました。

ご精読ありがとうございました。

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

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

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

GASサンプル集に戻る
メインメニューに戻る
これからプログラミングを始める方へ
基本情報技術者へ
自己紹介

←前に戻るにゃん    次行くにゃん(=^x^=) <最終回>→

paiza レベルアップ問題集 「STEP: 5 10 進数から 2 進数に変換」をPythonとGASで解いてみた

この記事を読むことで、PythonとGASで10進数から2進数に基数変換するコードの書き方を学べ、whileやForループの書き方、スライスを使った書き方、剰余演算子、リスト(配列の追加)など、プログラミングの基幹となる文法の習得を強化できます。

whileループで2で割った余りをリスト(配列)に格納し、Pythonではスライスを使ってForループでリストの逆順から表示させます。

別解として2進数に変換した計算結果をansという変数に格納するコードも記述しました。GASではこの別解に基づいてコードを書いています。

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

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

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

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

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

10 進数から 2 進数に変換 (paizaランク D 相当)

10 進数で表された整数 N が与えられます。
N を 2 進数に変換して出力してください。

この記事では、下記の入力例3の場合、10進数N=10が与えられた時に2進数でどのように変化していくかを求めて行きます。

入力例3
10

出力例3
1010

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

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

■ Pythonでの解き方 ■

下準備として、paiza.ioにこの様に入力します。
(入力例1をそのままioにコピーしただけ。)

手順として、

1:10進数の数値N=10を取得する

2:余りを格納する整数arrayを宣言する

3:whileループでN>=1の間、2で割り続けて余りをarrayに格納する

4:Forループでスライスを使ってarrayを逆順に取り出す

で、行います。

10進数を2進数に基数変換をする時は、下記のような2で割った余りを求めて、下から記述する方法で計算しました。
これは、10進数の10を2進数の「1010」に変換する時の計算過程です。

この図では、10を2で割った余りが「0」、5を2で割った余りが「1」、2を2で割った余りは「0」、最後1が残ります。
この余りを下から上に向かって「1010」と書くことで10進数の10を2進数の「1010」に変換出来ました。

この計算過程をwhileループを使って行います。
余りは配列arrayに順次追加して行きます。

まずは、プログラムの各変数の動きを追いやすいように、トレースのio出力結果と、トレースのコードを添えます。
Whileループのトレースをします。

1回目の除算

2回目の除算

3回目の除算

4回目の除算

余りを格納したリストをForループでスライスを使って逆から取り出しました。
以上を踏まえて、トレースのコードを掲載します。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

#whileループでN>=1の間、2で割り続けて余りをarrayに格納する

print('<<<ループに入る>>>')

while N>=1:
    print('除算前のリストarray:'+str(array))
    print('除算前のNの値:'+str(N))
    array.append(N%2)
    print('格納する余り:「'+str(N%2)+'」')
    
    N/=2
    N=int(N)
    print('除算後のNの値:'+str(N))
    print('除算後リストarray:'+str(array))
    print('------------------------')


print('<<<ループを抜ける>>>')    

#arrayを表示する
print(array)

#Forループを使って逆順から取り出す
for num in array[::-1]:
    print(num,end="")

#ループを抜けた所で改行をする
print()

このままでは、出力結果である出力例3に対して冗長なコードが含まれているので、解答以外のprint文をコメントアウトします。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

#whileループでN>=1の間、2で割り続けて余りをarrayに格納する

#print('<<<ループに入る>>>')

while N>=1:
    #print('除算前のリストarray:'+str(array))
    #print('除算前のNの値:'+str(N))
    array.append(N%2)
    #print('格納する余り:「'+str(N%2)+'」')
    
    N/=2
    N=int(N)
    #print('除算後のNの値:'+str(N))
    #print('除算後リストarray:'+str(array))
    #print('------------------------')


#print('<<<ループを抜ける>>>')    

#arrayを表示する
#print(array)

#Forループを使って逆順から取り出す
for num in array[::-1]:
    print(num,end="")

#ループを抜けた所で改行をする
print()

スッキリするように、コメントアウトした部分を省いたコードです。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

while N>=1:
    array.append(N%2)

    N/=2
    N=int(N)

#Forループを使って逆順から取り出す
for num in array[::-1]:
    print(num,end="")

#ループを抜けた所で改行をする
print()

ioの出力結果です。

上記ではスライスを使ってリストをForループで逆から取り出していましたが、リストを反転させて、[1,0,1,0]を1010と表記させる方法のコードを掲載します。

この部分を別解のコードでは、[1,0,1,0]を1010になるようにansという変数を使って、Forループで計算しています。

ansの初期値は0で10倍すると0、
そこにリストから「1」を加えると「ans=1」になります。
ans=1を10倍すると10、そこにリストから「0」を加えて「ans=10」になります。
ans=10を10倍すると100、そこにリストから「1」を加えて「101」になります。
ans=101を10倍すると1010、そこにリストから「0」を加えて「1010」になります。

そのForループのトレースと、コメントアウトをしたコード、コメントアウトを取り除いたコードを掲載します。

ループに入る前にリストを反転します。

1回目のansの計算

2回目のansの計算

3回目のansの計算

4回目のansの計算

以上を踏まえて、トレースのコードを掲載します。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

while N>=1:
    array.append(N%2)

    N/=2
    N=int(N)

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

#リストarrayを反転させる
array=list(reversed(array))

#反転させたリストarrayを出力
print(array)

#基数変換の計算結果を格納する変数ansを0で初期化
ans=0

#Forでリスト内の数を基数変換した形式で表示する

print('<<<Forループに入ります。>>>')

for num in array:
    print('計算前のans:'+str(ans))
    ans*=10
    print('10倍したans:'+str(ans))
    ans+=num
    print('計算後のans:'+str(ans))
    print('-------------------')

print('<<<Forループを抜けました>>>')


#基数変換の計算結果ansを表示させる
print(ans)

冗長な部分をコメントアウトしたコードです。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

while N>=1:
    array.append(N%2)

    N/=2
    N=int(N)

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

#リストarrayを反転させる
array=list(reversed(array))

#反転させたリストarrayを出力
#print(array)

#基数変換の計算結果を格納する変数ansを0で初期化
ans=0

#Forでリスト内の数を基数変換した形式で表示する

#print('<<<Forループに入ります。>>>')

for num in array:
    #print('計算前のans:'+str(ans))
    ans*=10
    #print('10倍したans:'+str(ans))
    ans+=num
    #print('計算後のans:'+str(ans))
    #print('-------------------')

#print('<<<Forループを抜けました>>>')


#基数変換の計算結果ansを表示させる
print(ans)

更にトレース部分のコメント部分を削除したコードです。


#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

while N>=1:
    array.append(N%2)
    N/=2
    N=int(N)


#リストarrayを反転させる
array=list(reversed(array))

#基数変換の計算結果を格納する変数ansを0で初期化
ans=0


#Forでリスト内の数を基数変換した形式で表示する

for num in array:
    ans*=10
    ans+=num

#基数変換の計算結果ansを表示させる
print(ans)

別解でも無事正解しました。

■ GASでの解き方 ■

では、同じ問題をGASで解いてみます。
まず、スプレッドシートにこの様に配置しました。

スプレッドシートの黄色いセルの所に「10進数N(=10)を2進数に基数変換をした結果1010」を出力します。
基数変換の計算結果はansに格納します。
また、ansを二次元配列ans2に追加して、スプレッドシートに出力します。

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

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

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

2:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する


3:2で割った余りを格納する配列を宣言する


4:whileループを使って余りを配列に格納する


5:配列を表示


6:配列を反転させる


7:反転した配列を表示


8:2進数を変数ansに格納する為、ansを0で初期化する

9:ループで2進数を計算する

10:ansを表示

11:スプレッドシートに格納する二次元配列ans2を宣言

12:ansをans2に二次元配列として格納

13:スプレッドシートに出力前にans2を出力して確認する

14:スプレッドシートの黄色い所に2進数に基数変換した結果を格納する

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

const ss=SpreadsheetApp.getActiveSheet();

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

手順2:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する

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

※Nを2で割っていくので、Nの値が変わる、すなわち変数なので定数のconstではなく変数のletで宣言をします※

手順3:2で割った余りを格納する配列を宣言する

let array=[]

手順4:whileループを使って余りを配列に格納する

1回目の除算

2回目の除算

3回目の除算

4回目の除算

whileループのコードの部分です。

//whileループを使って余りを配列に格納する

  console.log('<<<whileループに入る>>>');

  while(N>=1){
    console.log(`除算前のNの値:${N}`);
    console.log(`除算前の配列array[${array}]`);
    //配列に余りを追加する
    array.push(N%2);
    console.log(`余り:${N%2}`);
    //除算実行
    N/=2;
    //小数点を切り捨てる
    N=Math.floor(N);
    
    console.log(`除算後のNの値:${N}`);
    console.log(`除算前の配列array[${array}]`);
    console.log('--------------------');

  }

  console.log('<<<whileループを抜けました。>>>');

手順5:配列を表示

console.log(array);

手順6:配列を反転させる

array=array.reverse();

手順7:反転した配列を表示

console.log(array);

配列の反転前と反転後のログです。

手順8:2進数を変数ansに格納する為、ansを0で初期化する

let ans=0;

手順9:Forループで2進数に基数変換する

1回目のansの計算

2回目のansの計算

3回目のansの計算

4回目のansの計算

Forループの部分のコードです。

console.log('<<<Forループに入る>>>');

  //ループで2進数を計算する
  for(let i=0;i<=array.length-1;i++){
    console.log(`計算前のansの値:${ans}`);
    ans*=10;
    console.log(`10倍したansの値:${ans}`);
    ans+=array[i];
    console.log(`計算後のansの値:${ans}`);
    console.log('---------------------------');
  }

  console.log('<<<Forループを抜けました。>>>');

手順10:ansを表示

console.log(ans);

手順11:スプレッドシートに格納する二次元配列ans2を宣言

let ans2=[];

手順12:ansをans2に二次元配列として格納

ans2.push([ans]);

手順13:スプレッドシートに出力前にans2を出力して確認する

console.log(ans2);

手順14:スプレッドシートの黄色い所に2進数に基数変換した結果を格納する

ss.getRange(3,2).setValue(ans2);

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

function loop2no10(){

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


  //スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する
  let N=ss.getRange(1,2).getValue();

  
  //2で割った余りを格納する配列を宣言する
  let array=[]
  
  
  //whileループを使って余りを配列に格納する

  console.log('<<<whileループに入る>>>');

  while(N>=1){
    console.log(`除算前のNの値:${N}`);
    console.log(`除算前の配列array[${array}]`);
    //配列に余りを追加する
    array.push(N%2);
    console.log(`余り:${N%2}`);
    //除算実行
    N/=2;
    //小数点を切り捨てる
    N=Math.floor(N);
    
    console.log(`除算後のNの値:${N}`);
    console.log(`除算前の配列array[${array}]`);
    console.log('--------------------');

  }

  console.log('<<<whileループを抜けました。>>>');


  //配列を表示
  console.log(array);

  //配列を反転させる
  array=array.reverse();

  //反転した配列を表示
  console.log(array);

  //2進数を変数ansに格納する為、ansを0で初期化する
  let ans=0;

  console.log('<<<Forループに入る>>>');

  //ループで2進数を計算する
  for(let i=0;i<=array.length-1;i++){
    console.log(`計算前のansの値:${ans}`);
    ans*=10;
    console.log(`10倍したansの値:${ans}`);
    ans+=array[i];
    console.log(`計算後のansの値:${ans}`);
    console.log('---------------------------');
  }

  console.log('<<<Forループを抜けました。>>>');

  //ansを表示
  console.log(ans);

  //スプレッドシートに格納する二次元配列ans2を宣言
  let ans2=[];

  //ansをans2に二次元配列として格納
  ans2.push([ans]);

  //スプレッドシートに出力前にans2を出力して確認する
  console.log(ans2);

  //スプレッドシートの黄色い所に2進数に基数変換した結果を格納する
  ss.getRange(3,2).setValue(ans2);

}

宜しかったらコピペしてアレンジして見て下さい。
お疲れ様でした、ブレイクタイムフォトはこちらになります。

みなとみらいの海と夜景

■ 参考文献の紹介■

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

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

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

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

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

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