• ベストアンサー

再帰

お世話になります。再帰でどう組んだらいいのかわからない問題があるので質問させてください 問題は、再帰を使ってlong型の整数に、3つずつの間隔でコンマを入れString型で返す演習問題です。 例) 999 → 999 1234 → 1,234 1007 → 1,007 1023004567 → 1,023,004,567 public static String intWithCommas(long n) { String strnum = String.valueOf(n); String str = ""; int length = strnum.length(); if (strnum.length() <= 3) { return strnum; } else { str = "," + strnum.substring(length-4, length-1); } return str + intWithCommas(?); } 上記のように組んだのですが、2箇所わからないところがあります。 カンマを入れるので整数を文字列に変換してsubstringで3つずつに分けてカンマを入れようと思ったのですが、 str = "," + strnum.substring(length-4, length-1); この部分をどのように直したらいいかがわかりません。 これではカンマが一番左に行ってしまうし、整数を3つずつにわけようにも、本来インデックスは左から数えますがこの場合は右から3つずつ数えなければなりません。 それと、最後の再帰を呼ぶところですが、intWithCommas(?);の中をどうしたらいいかがわかりません。 long型の整数を受け取ってるのでlong型の整数を入れるとおもうのですが、プログラムの中で整数をStringに変換してるのでどうしたらよいのでしょうか 宜しくお願いします。

  • Java
  • 回答数2
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • anmochi
  • ベストアンサー率65% (1332/2045)
回答No.1

 毎回String型のインスタンスを作ってsubstring()は効率悪すぎっしょ(1回の再起につき2つのStringインスタンスが作成される)。比較(1000以上か未満か)だってlongのまま行う方が高速だ。  もうちょっとシンプルに考えてみたらどうかな。たとえば以下のようなものはどうだろう。課題という事なんでそのものズバリを書いてしまうのは抵抗があるけど、String型に変えてからごにょごにょという事にこだわらないという例を示したいので。 package anmochi; import java.text.*; public class NumericFormat {   public static String intWithCommas(DecimalFormat df, long n) {     if(n < 1000) { // 1000未満なら       return String.valueOf(n); // そこが最上位     } else { // 1000を含むそれ以上なら       return intWithCommas(df, n / 1000) + "," + df.format(n % 1000); // 1000で割った数値を再起で処理させて、自分は1000未満の部分だけを"000"でフォーマットする。※1     }   }   public static void main(String[] args) {     DecimalFormat df = new DecimalFormat("000");     System.out.println(intWithCommas(df, 1));     System.out.println(intWithCommas(df, 20));     System.out.println(intWithCommas(df, 999));     System.out.println(intWithCommas(df, 1000));     System.out.println(intWithCommas(df, 65535));     System.out.println(intWithCommas(df, 1123456789));   } }  今この回答上にざっと書いただけなので動作確認はしてません。よろしく。  また、DecimalFormatも1つのインスタンスを使いまわしたいだけなので再起メソッドの引数に含まれるのは今回の本質ではないというのも注意。といいつつ※1のところでStringインスタンスが何個も作られてるけど。

lockwell
質問者

お礼

解決しました!ありがとうございます!

lockwell
質問者

補足

どうもありがとうございます。 一つ質問があるのですが、整数が1007だった場合、1000で割ると商が1で余りが7になります。 そうすると結果が1,7になり、余りでは00が無視されてしまいます。 1000を1000で割っても商が1、余りが0なので1,0となります 余りで0を省略されないようにするにはどうしたらよいのでしょうか DecimalFormatの部分も少し解説していただけますでしょうか

その他の回答 (1)

  • Tasuke22
  • ベストアンサー率33% (1799/5383)
回答No.2

> str = "," + strnum.substring(length-4, length-1); ","+(n/1000の余りの文字列) > return str + intWithCommas(?); return intWithCommas(n/1000) + str; 下から処理するので、再帰は上へ継ぎ足す。

lockwell
質問者

お礼

解決しました!ありがとうございました!

lockwell
質問者

補足

ありがとうございます。 ","+(n/1000の余りの文字列)この部分ですが、上にもすでに書いたように、1000や1007といった1000で割ったとき余りで0が省略されてしまう場合はどのように処理したらよいでしょうか 1007の余りは007ではなく7となってしまうので、結果1,007ではなく1,7となってしまいます

関連するQ&A

  • array_mapの再帰処理がうまく行かない

    長文で失礼します。 array_mapでの再帰処理がうまく行かないのでどこが間違っているか教えてください。 まず、このような配列があります。配列の中に配列があります。 $ary = array(1, 2, null, array("a", null, "c")); この配列の中のnullを"なし"という文字列に変換したいです。 array_mapを使って再帰的にやってみました。 まずはうまく行ったコードから。 ------------------------------------------------------ $ary = array(1, 2, null, array("a", null, "c")); var_dump(null2Nashi($ary)); // nullを"なし"に置換する関数 function null2Nashi(  $in_array ){  if(is_array($in_array)){   return array_map("null2Nashi", $in_array);  } else {   if ($in_array === null){    $in_array = "なし";   }   return $in_array;  } } ------------------------------------------------------ 結果はnullが"なし"に変換されました array (size=4)  0 => int 1  1 => int 2  2 => string 'なし' (length=6)  3 =>   array (size=3)    0 => string 'a' (length=1)    1 => string 'なし' (length=6)    2 => string 'c' (length=1) そしてこの"なし"をコード内で指定するのではなく引数で指定したいと思って無名関数を使って以下のコードにしました。 ------------------------------------------------------ $ary = array(1, 2, null, array("a", null, "c")); var_dump(null2Str($ary, "なし")); // nullを指定文字列に置換する関数 function null2Str(  $in_array, // null値を含む配列  $in_str // null値を変換したい文字列 ){  $n = function($n_array) use($in_str){   if(is_array($n_array)){    return array_map($n, $n_array); //…(1)   } else {    if ($n_array === null){     $n_array = $in_str;    }    return $n_array;   }  };  return $n($in_array); } ------------------------------------------------------ 結果はnullは何も変換されませんでした。 array (size=4)  0 => int 1  1 => int 2  2 => null  3 =>   array (size=3)    0 => string 'a' (length=1)    1 => null    2 => string 'c' (length=1) どうやら(1)のarray_mapが動作していないようです。要素を分解せずに$nの無名関数に渡さずにそのまま第2引数を返しているだけみたいです。 何か対応方法があるでしょうか? どうぞよろしくお願い致します。

    • ベストアンサー
    • PHP
  • 木構造と再帰

    1週間考えましたが分かりません 正の整数mとn(n <= 9)を入力して、1以上n以下のn個の数字を自由に組み合わせて構成されるm桁の数字列のすべてを表示するJavaのプログラムである。 以下に、本プログラムの動作例を示す。 桁数を入力してください 4(入力) 1以上9以下の整数を入力してください 2(入力) 1111 1112 1121 1122 1211 1212 1221 1222 2111 2112 2121 2122 2211 2212 2221 2222 このとき、本プログラムのsetNode()メソッドの中身を記述してプログラムを完成させよ。ただし、setNodeメソッドは再帰的手続きとし、プログラムのほかの部分を変更(追加、削除を含めて)しないこと。 import java.io.*; class Node { private int value; private Node child[]; public void setNode(int value, int digit, int range); { //ここに解答 } public int getValue() { return value; } public Node getChild(int index) { return child[index]; } } class NumberString { static int range; public static void main(String args[]) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.plintln("桁数を入力してください"); String str1 = br.readLine(); int digit = Integer.parseInt(str1); System.out.plintln("1以上9以下の整数を入力してください"); String str2 = br.readLine(); range = Integer.parseInt(str2); Node root = new Node(); root.setNode(0, digit, range); for(int i = 0;i < range; i++){ printNumber(root.getChild(i), digit, ""); } } private static void printNumber(Node n, int digit, String str) { if(digit == 1){ System.out.plintln(str + n.getValue()); return; } for(int i = 0;i < range;i++){ printNumber(n.getChild(i), digit - 1, str + n.getValue()); } } }

    • ベストアンサー
    • Java
  • Python 再帰関数関連

    再帰関数を解決できなくて困っています、ご教授お願いします! 普通関数で書いたものを再帰関数に変換するのはどう書けばいいですか? def foo(n, m):  sum = 0 while m > 0: sum = sum + n m = m -1 return sum これを再帰関数でどう変換します?

  • 再帰関数について

    非負の整数nに対して次のように定義された 関数F(n),G(n)がある。F(5)の値はいくらか。 関数 F(n):if n=<1 then return1 else return n×G(n-1) G(n):if n=0 then return0 else return n+F(n-1) (1)50 (2)65 (3)100 (4)120 正解 (2)65 以下解説 F(5):5×G(5-1)=5×(G(4))    =5×(4+F(4-1))=5×(4+(F(3)))    =5×(4+(3×G(3-1)))=5×(4+(+3×G(2))))    =5×(4+(3×(2+F(2-1))))=5×(4+(+3×(2+F(1)))))    =5×(4+(3×(2+(1))))    =65 再帰関数についての知識が皆無なので 教えて頂きたいのですが、なぜ=後の5×は残るのでしょうか。 そもそも再帰関数とは、どんなことを言っているのでしょうか。 具体例を挙げて頂くか、分かり易いURLを教えて頂けると幸いです。 お手数ですが、上記について1つ1つ丁寧に解説して頂きたいです。 大変ご迷惑な質問かと思いますが、分かる方おられましたら、 お手数ですが、ご教授お願いします。 以上、よろしくお願い致します。

  • 【C言語】再帰を用いるプログラムでのセグフォ

    明解C言語入門編のp196にあるList8-7 再帰を用いて2つの整数の最大公約数を求めるプログラムなんですが #include<stdio.h> int gcdf(int vx, int vy) { return(vy == 0? vx: gcdf(vy,vx&vy)); } int gcd(int va, int vb) { return(va>vb? gcdf(va,vb): gcdf(vb,va)); } としてmainの中で入力された2つの整数n1,n2を 最大公約数としてgcd(n1,n2)を表示させるのですが、 (1,2)とか(2,4)などの再帰が1度しか行われない(?)プログラムでは ちゃんと結果が表示されるのですが、 (4,6)など再帰が2度以上行われるプログラムになると segmentation fault(コアダンプ) と表示されます。 どこに問題があるのでしょうか OSはubuntu14.04 エディタはvim コンパイラはclangです。 よろしくお願いします。

  • 再帰

    他の質問と平行してしまい申し訳ありません。再帰について少々おききしたいのですが、 配列の中にある数字の中から最大値と最小値を再帰処理でもとめたいのですが、うまくいきません。 public int minMax(n, array, min, max){ // nは配列のサイズです。 min=max=array[n-1]; if(array[n-2]<min) min=array[n-2]; if(array[n-2]>max) max=array[n-2]; return minMax(n-1,array,min,max); } 最初に比較するために min=max=array[n-1];と初期化したのですが、再帰処理ですからまた同じ初期化をしてしまうことになります。 forループなどを使えるなら初期化だけループの外でやれば済むのですが、再帰だとどのようにすればよいのでしょうか。 宜しくお願いいたします。

  • string型からint型への型変換

    C++で、string型からint型は、 string str; //ほかのstring型の変数から整数部分のみを切り出して来たものが入る int i; //ここにstrの中身(整数)をあらたに入れたい が定義されている下で、 char s[10]="0"; などを通して、 int length=str.length(); str.copy(s,length,0); i=atoi(s); とやる他ないのでしょうか? 初心者のつまらない質問ですが、ご教授いただけると幸です。 よろしくお願いします。

  • 関数の再帰処理

    1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657... という数列(フィボナ数列)を再帰処理でだしたいのですが・・・・・ include <stdio.h> int function( int ); int main( void ){ int n; do { printf( "0 以上の整数値を入力して下さい→ " ); scanf( "%d", &n ); }while ( n < 0 ); printf( "計算結果: %d\n", function( n ) ); getchar(); getchar(); return 0; } int function( int n ){ //フィボナの処理(function)の再帰呼び出しによる } function内に再帰処理を用いてprintf( "計算結果: %d\n", function( n ) );で画面出力したいのですが・・・・・・。

  • 再帰呼び出しの計算量

    再帰呼び出しを用いた関数の計算量を求める方法がわからないので質問させていただきます. xのn乗を再帰呼び出しを用いて求める関数に関して,計算量を求める問題なのですが,どのような方針で求めればよいのでしょうか? int exponent(int x, int n) {   if(n == 0){     return 1;   }else{     return x * exponent(x, n-1);   } } exponentがn回呼ばれるからO(n)というのは間違いでしょうか?

  • 再帰的に処理をする方法

    まとめてサニタイズする方法として下記のように書いてみました。 引数が配列でなければ問題ないのですが、配列だとこんなエラーが出ます。 Warning: array_map() expects parameter 1 to be a valid callback, function 'sanitize' not found or invalid function name in ファイル名 foreachでまわすのも考えましたが、できるならスマートにと思っているのですが どうすれば再帰的な処理ができるでしょうか? $valid = new Valid(); $array = array( 'あああ','いいい','ううう', ); $valid->sanitize( $array ); class Valid{ public function sanitize( $str ){ if ( is_array( $str ) ) return array_map( 'sanitize', $str ); return str_replace( "\0", '', $str ); } }

    • ベストアンサー
    • PHP

専門家に質問してみよう