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サンプル
基本情報技術者試験

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

投稿者: nekosiestr

プログラミング学習中のロスジェネ(就職氷河期世代)の発達障害者です。 宜しくお願いします。 趣味で写真を撮っています。 プログラミングは、GAS/HTML/CSS/JavaScript/jQuery/PHP、 発達障害は、自閉症スペクトラムASD/ADHD、その他双極性障害やHSP(5人に1人の繊細さん)などの生きづらさを抱えておりますが、それでも楽しく生きて行きたいです!! 写真は、以前はコンパクトデジカメ、現在は、OLYMPUSミラーレス一眼を使っています。