challenge 九九の表示

掛け算の九九を下のように表示してください。

1 * 1 =  1
1 * 2 =  2
1 * 3 =  3
(略)
7 * 8 = 56
7 * 9 = 63
8 * 1 =  8
8 * 2 = 16
8 * 3 = 24
8 * 4 = 32
(略)
9 * 8 = 72
9 * 9 = 81

なお、この問題は掛け算をどうやるかではなく、 どうやって右端がそろうようにレイアウトするかに重点を置いているので、 下のようなへこんだ出力は禁止です。

7 * 9 = 63
8 * 1 = 8
8 * 2 = 16
動的にサイズを変えられるようにしてみました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
        static void Main(string[] args)
        {
            kuku(9);
            kuku(99);
            kuku(999);
        }

        static void kuku(int n)
        {
            int len = n.ToString().Length;
            int xLen = (n * n).ToString().Length;
            string    format = "{0, " + len + "} * {1, " + len + "} = {2, " + xLen + "}";

            for (int i = 1; i <= n ; ++i)
                for (int j = 1; j <= n ; ++j)
                    Console.WriteLine(format, i, j, i * j);
        }
面白くない答えですが・・・

sayは、printlnだと思ってください。
t_ishida
1
for(var i=1;i<10;i++) for(var j = 1;j<10;j++) say([i,'*',j,'=',''].join(' ') + (i * j > 9 ? '' : ' ') + i * j);

Posted feedbacks - Nested

Flatten Hidden
そのまんま
1
2
3
4
5
(1..9).each{|x|
  (1..9).each{|y|
    printf("%d * %d = %2d\n", x,y,x*y)
  }
}
Text.Printf モジュールを使う
1
2
3
4
5
import Text.Printf

main = putStr . unlines . map showKuKu $  [(i,j,i*j) | i <- [1..9], j <- [1..9] ]
showKuKu :: (Int,Int,Int) -> String
showKuKu (i,j,k) = printf "%d * %d = %2d" i j k
指定した数の二乗までのかけ算の表示ができるようにした。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
module Main (main) where

import System.Environment
import Text.Printf

main :: IO ()
main = do { args <- getArgs
          ; let n = case args of { [] -> 9; a:_ -> read a }
          ; putStr . unlines . map (showKuku (keta n) (keta (n*n))) 
          $ [ (i,j,i*j) | i <- [1..n], j <- [1..n] ]
	  }

showKuku :: Int -> Int -> (Int,Int,Int) -> String
showKuku l l' (i,j,ij) = printf ("%"++k++"d * %"++k++"d = %"++k'++"d") i j ij
  where k  = show l
        k' = show l'

keta  = length . show 

{-
*Main> :main 19
途中略
 6 * 16 =  96
 6 * 17 = 102
 6 * 18 = 108
 6 * 19 = 114
 7 *  1 =   7
 7 *  2 =  14
 7 *  3 =  21
 7 *  4 =  28
以下略
-}
インドでも使える版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?php
function print_kuku($max) {
    $len1 = strlen($max);
    $len2 = strlen(pow($max, 2));
    
    for ($i = 1; $i <= $max; $i++) {
      for ($j = 1; $j <= $max; $j++) {
        printf("%{$len1}s * %{$len1}s = %{$len2}s\n", $i, $j, $i*$j);
      }
    }
}

print_kuku(9); //日本
print_kuku(20); //インド
?>
あえて1行で書いてみました。
1
BEGIN { for (i=1;i<=9;i++) for (j=1;j<=9;j++) printf("%d * %d = %2d\n",i,j,i*j); exit }
おなじく一行python版です。
1
print '\n'.join(['%d * %d = %2d' % (i, j, i*j) for i in range(1, 10) for j in range(1, 10)])
printf にかっこはいらない
BEGIN の最後に exit はいらない
まあそうなんですが
普通に。
1
2
3
for i in xrange(1, 10):
    for j in xrange(1, 10):
        print "%d * %d = %2d" % (i, j, i * j)
マニピュレータを使用。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <iostream>
#include <iomanip>

int main()
{
    for (int i = 1; i <= 9; ++i)
    {
        for (int j = 1; j <= 9; ++j)
        {
            std::cout << i << " * " << j << " = "
                      << std::setw(2) << (i * j) << std::endl;
        }
    }
}
再帰版
1
2
3
4
5
(defun kuku (&optional (x 1) (y 1))
  (cond ((and (= x 9) (> y 9)) nil)
        ((> y 9) (terpri) (kuku (1+ x) 1))
        (t (format t "~D * ~D = ~2D~%" x y (* x y))
           (kuku x (1+ y)))))

ふつう

1
2
3
4
import System.out.printf
for(i <- (1 to 9); j <- (1 to 9)) {
  printf("%d * %d = %2d\n", Array(i,j,i*j).map{_.asInstanceOf[AnyRef]})
}

	
1
2
3
4
my %count;
for my $j (map {($_) x 9} 1..9){
  printf "%d * %d = %2d\n",$j,++$count{$j},$count{$j}*$j;
}
意味があるか不明だけど、更に行数減らせますね。
1
map {printf "%d * %d = %2d\n",$_,++$count{$_},$count{$_}*$_} (my %count, map {($_) x 9} 1..9);
2桁の九九も目的どおり動きます。
書式に*をつかうのがポイント。
ただ、答えに余計な空白が入ることがあります。

19の段がこんな感じに
19 *  1 =   19
19 *  2 =   38
19 *  3 =   57
19 *  4 =   76
19 *  5 =   95
19 *  6 =  114
19 *  7 =  133
19 *  8 =  152
19 *  9 =  171
19 * 10 =  190
19 * 11 =  209
19 * 12 =  228
19 * 13 =  247
19 * 14 =  266
19 * 15 =  285
19 * 16 =  304
19 * 17 =  323
19 * 18 =  342
19 * 19 =  361

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>

#define START 1
#define END   19

int main()
{
    int col; /* 段 */
    int row; /* 行 */
    int digit;        /* 段・行の桁数 */
    int answer_digit; /* 答えの桁数   */
    int tmp;

    digit = 1;
    for (tmp = END; tmp/10 != 0; digit++) {
        tmp %= 10; 
    }   
    answer_digit = digit * 2;

    for (col = START; col <= END; col++) {
        for (row = START; row <= END; row++) {
            printf("%*d * %*d = %*d\n", digit, col,
                                        digit, row,
                                        answer_digit, col * row);
        }
    }

    return 0;
}
printfは使えないので。
1
2
3
4
5
6
7
8
9
function lpad(str, n) {
  return str.length < n ? (new Array(n - str.length + 1).join(' ') + str) : str;
}
var n = 10;
for(var i=1; i<n; i++) {
  for(var j=1; j<n; j++) {
    pp(i + " * " + j + " = " + lpad('' + (i * j), 2));
  }
}
すみません。上記のpp関数は自分のローカル用デバッグ出力関数です。
rhinoならprintとかに置き換えてください。

で、↓はalertで表示する場合。
100行alertはひどいので10回に分けて。
alertのフォントは普通プロポーショナルなのが悲しいところ。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function lpad(str, n) {
  return str.length < n ? (new Array(n-str.length+1).join(' ') + str) : str;
}
var n = 10;
var list = [];
for(var i=1; i<n; i++) {
  for(var j=1; j<n; j++) {
    list.push(i + " * " + j + " = " + lpad('' + (i*j), 2));
  }
  alert(list.join("\n"));
  list = [];
}
自分で書けば使えないことはないんじゃないですか。
高度な JavaScript 技集のprintfのことは知ってましたよ。
でも、このお題満たすためにprintfを実装するのはどう考えてもオーバースペックですよね。

ひょっとして「使えない」の解釈が違うのかもしれませんが、このサイトではありもののライブラリを使うのは禁止されてるわけでも忌避されてるわけでもないので、あるんだから使えばいいじゃんと思いますけども。知ってたなら尚更。

もちろんいちからprintfを車輪の再発明するのはいくらなんでもめんどくさいってのは否定しません。


	
1
2
3
4
5
6
7
class Program {
    static void Main(string[] args) {
        for (int x = 1; x <= 9; x++)
            for (int y = 1; y <= 9; y++)
                System.Console.WriteLine("{0} * {1} = {2,2}", x, y, x * y);
    }
}
再帰版ver.2

二桁の場合にも右端が揃うように汎用性を持たせてみました。

例:(kuku 19)
(省略)
19 *  1 =  19
19 *  2 =  38
19 *  3 =  57
19 *  4 =  76
19 *  5 =  95
19 *  6 = 114
19 *  7 = 133
19 *  8 = 152
19 *  9 = 171
19 * 10 = 190
19 * 11 = 209
19 * 12 = 228
19 * 13 = 247
19 * 14 = 266
19 * 15 = 285
19 * 16 = 304
19 * 17 = 323
19 * 18 = 342
19 * 19 = 361
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(defun kuku (n)
;nの桁数をlen1,最も大きな積(n*n)の桁数をlen2とする
    (let ((len1 (digits n))
          (len2 (digits (* n n))))
       (sub n len1 len2)))

(defun sub (n len1 len2 &optional (x 1) (y 1))
  (cond ((and (= x n) (> y n)) nil)
        ((> y n) (sub n len1 len2 (+ x 1) 1))
        (t (print-space (- len1 (digits x)))
           (format t "~D * " x)
           (print-space (- len1 (digits y)))
           (format t "~D = " y)
           (print-space (- len2 (digits (* x y))))
           (format t "~D~%" (* x y))
           (sub n len1 len2 x (+ y 1)))))

;桁数を数える
(defun digits (m &optional (d 0))
  (cond ((zerop m) d)
        (t (digits (floor m 10) (incf d)))))

;空白を出力
(defun print-space (space-num)
  (dotimes (i space-num)
    (format t " ")))
答えの欄に空白置いて、答えの桁数だけ^H(backspace)吐いて、答え書く。

(管理者追記:ソースコード中の制御コードが原因でRSSがvalidでなくなっていたので、 とりあえず削除しました。bsは空文字列のようになっていますが、実際には0x08が2つ入っていました。)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash
bs=""
# bs="^H^H"
for n in $(seq 1 9); do
	for m in $(seq 1 9); do
		p=$(($n*$m))
		echo -n $n' * '$m' =   '
		echo ${bs:0:${#p}}$p
	done
done
printf使うのは素直過ぎて。
1
2
#!/bin/bash
for n in $(seq 9); do for m in $(seq 9); do echo $n' * '$m' = '$(printf '%2g' $(($n*$m))); done; done
ibazaさん(#3088)のきれいな解答の後で投稿するのは恥ずかしいのですが、doループで…。
おまけで9*9以上にも対応してみました…。
1
2
3
4
5
6
7
(defun print-kuku (&optional (n 9))
  (let* ((dn (1+ (truncate (log (expt n 2) 10))))
	 (dnn (1+ (/ dn 2))))
    (do ((i 1 (1+ (mod i n)))
	 (j 1 (if (= i n) (1+ j) j)))
	((> j n))
      (format t "~:[~;~%~]~VD *~VD = ~VD~%" (= i 1) dnn j dnn i dn (* j i)))))
Squeak Smalltalk で。

#format: は単に文字列指定箇所への埋め込みのみで、printf の書式指定のような細やかな機能はないので、数値の文字列変換に際し、要求にあわせてあらかじめ整形しておく必要があります。

今回は、第一引数の文字で第一引数の文字数に足りない分を左側から追加して埋める #printPaddedWith:to: というメソッドを使用しました。

なお、$ は Smalltalk での文字オブジェクトリテラルに冠する記号で、直後に続く一文字(下の場合、スペース)に相当する文字オブジェクトを返します。
1
2
3
World findATranscript: nil.
1 to: 9 do: [:x | 1 to: 9 do: [:y |
    Transcript cr; show: ('{1} * {2} = {3}' format: {x. y. (x * y) printPaddedWith: $  to: 2})]]
第一引数の文字数 → 第二引数の文字数
Gauche
srfi-42とutil.matchを使った
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
(use srfi-42)
(use util.match)

(define (display99 n)
  (let* ((k (string-length (x->string n)))
         (k2 (string-length (x->string (* n n))))
         (fmt (string-append "~" (x->string k) "d * ~" (x->string k) "d = ~" (x->string k2) "d~%")))
    (define (f x)
      (match x
        ((i j ij) (format #t fmt i j ij))))
    (for-each f (list-ec (: x 1 (+ n 1)) (: y 1 (+ n 1)) (list x y (* x y))))
    (values)))
nobsun関数型脳に侵されていますね :-) lazy脳というべきか。
do-ecを使うとループの中で直接副作用を起こすことができます。
Haskellerにとってはcomposableでないのが気持ち悪いでしょうが…

あと、formatは直接幅指定ができます。 ~2d で2桁。
~vd と書くと幅自体を引数で渡すこともできます (displayNN参照)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
(use srfi-42)

(define (display99 n)
  (do-ec (: x 1 (+ n 1)) (: y 1 (+ n 1))
         (format #t "~d * ~d = ~2d~%" x y (* x y))))

;; n >= 10 にも対応
(define (displayNN n)
  (let ((w0 (string-length (number->string n)))
        (w1 (string-length (number->string (* n n)))))
    (do-ec (: x 1 (+ n 1)) (: y 1 (+ n 1))
           (format #t "~vd * ~vd = ~vd~%" w0 x w0 y w1 (* x y)))))
> nobsun関数型脳に侵されていますね :-) lazy脳というべきか。
バレてる :)
> ~vd と書くと幅自体を引数で渡すこともできます
これもありそうだなと投稿してから気づいたのでした。

というわけでScheme版をHaskell版へ逆輸入


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import Text.Printf

displayNN n 
 = sequence_
 $ do { i <- s
      ; j <- s
      ; return $ putStrLn $ printf fmt i j (i*j)
      }
   where 
     s   = [1..n]
     k   = length $ show n
     k'  = length $ show (n*n)
     fmt = printf "%%%dd * %%%dd = %%%dd" k k k'
Text.Printf.printf でも * フラッグが使えるのでした。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import Text.Printf

displayNN :: Int -> IO ()
displayNN n 
 = sequence_ 
 $ do { i <- [1..n] ; j <- [1..n]
      ; return $ putStrLn $ printf "%*d * %*d = %*d" k i k j k' (i*j)
      }
   where k  = length $ show n
         k' = length $ show (n*n)
C#では複合書式を使用していたのでPadLeftで。
1
2
3
4
5
For i As Integer = 1 To 9
    For j As Integer = 1 To 9
        Console.WriteLine(i.ToString & " * " & j.ToString & " = " & (i * j).ToString.PadLeft(2))
    Next
Next
初投稿。思いつきで、何の工夫もなし。
1
2
3
4
5
(1..9).each do |i|
  (1..9).each do |j|
    puts "#{i} * #{j} " << "= " << (i * j).to_s.rjust(2)
  end
end
ちょっと細かいところだけど、
puts "#{i} * #{j} " << "= " << (i * j).to_s.rjust(2)
を
puts "#{i} * #{j} = " << (i * j).to_s.rjust(2)
に直した。
1
2
3
4
5
(1..9).each do |i|
  (1..9).each do |j|
    puts "#{i} * #{j} = " << (i * j).to_s.rjust(2)
  end
end