challenge ビンゴの結果を整形表示

重複無し乱数」の続編です。

「重複無し乱数」で作ったbingo関数の結果を下のように「何番目の乱数か」とセットにして10個ずつ折り返して表示するコードを書いてください。

>>> bingo(30)
  1  2  3  4  5  6  7  8  9 10
 29 14 16 13 30 15 22 11 25  9

 11 12 13 14 15 16 17 18 19 20
 23  4 18  5 28 17  8 12 21 20

 21 22 23 24 25 26 27 28 29 30
 26  6  2 19  1  7 10 27  3 24

>>> bingo(35)
  1  2  3  4  5  6  7  8  9 10
  7 15  3 32  1 16 17 28  6 29

 11 12 13 14 15 16 17 18 19 20
 19 23 30 26 20  5 12  2 25 31

 21 22 23 24 25 26 27 28 29 30
 35 13 24 18 11  8 10 34 22 21

 31 32 33 34 35
  9  4 27 33 14

Posted feedbacks - Nested

Flatten Hidden
enumeratorで
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def bingo(num)
	(1..num).to_a.sort_by{ rand }
end

require 'enumerator'
bingo(35).enum_slice(10).each_with_index{ |e,index|
	num=index * 10 + 1
	tmpl=(["%02s"] * e.size).join(' ')

	puts tmpl % (num .. num + e.size).to_a
	puts tmpl % e
	puts ""
}
リストを選んだ意味があまりなくなってしまいましたが、前のお題にそのまま出力機能を加えました。
 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
import java.util.*;

public class Sample2 {
    public static List<Integer> bingo(int num) {
        Integer[] deck = new Integer[num];
        for (int i = 0; i < num; i++) {
            deck[i] = i + 1;
        }
        List<Integer> nums = (List<Integer>) Arrays.asList(deck);
        Collections.shuffle(nums);
        return nums;
    }

    public static void printBingo(int num) {
        List<Integer> nums = bingo(num);
        for (int j = 0; j < num; j += 10) {
            for (int i = j; i < j + 10 && i < num; i++) {
                System.out.printf("%3d", i + 1);
            }
            System.out.println();
            for (int i = j; i < j + 10 && i < num; i++) {
                System.out.printf("%3d", nums.get(i));
            }
            System.out.printf("%n%n");
        }
    }

    public static void main(String[] args) {
        printBingo(Integer.parseInt(args[0]));
    }
}
showBingoがビンゴの整数リストを文字列に変換する
関数。第一引数は数字の最大桁数
shuffle は前回と同じだけど再掲
 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
module Main (main) where

import Data.List
import System.Environment
import System.Random
import Text.Printf

shuffle :: [a] -> StdGen -> Int -> [a] -> [a]
shuffle acc _ 0 _  = acc
shuffle acc g n xs = case randomR (0,n-1) g of
 (i,g') -> case splitAt i xs of
             (ys,z:zs) -> shuffle (z:acc) g' (n-1) (ys++zs)

main :: IO ()
main = do { x:_ <- getArgs
          ; g0  <- getStdGen
          ; let n = read x
          ; putStr $ showBingo (length x)
          $ shuffle [] g0 n [1..n]
          }

showBingo :: Int -> [Int] -> String
showBingo w = unlines . map (showLines w) . map unzip . slice 10 . zip [1..]

slice :: Int -> [a] -> [[a]]
slice n = unfoldr phi
  where phi [] = Nothing
        phi xs = Just $ splitAt n xs

showLines :: Int -> ([Int],[Int]) -> String
showLines n (xs,ys) = unlines [ unwords $ map (pr n) xs
                              , unwords $ map (pr n) ys]

pr :: Int -> Int -> String
pr w = printf $ "%"++show w++"d"

{-
% ./bingo 30
 1  2  3  4  5  6  7  8  9 10
19 26  2  6 11 17 23  8  7  5

11 12 13 14 15 16 17 18 19 20
18 13 16 12 22 24  4 21  1 25

21 22 23 24 25 26 27 28 29 30
 3 29 10 27 15  9 28 14 20 30

% ./bingo 35
 1  2  3  4  5  6  7  8  9 10
20 32 18  3 29 13 33  1 24 21

11 12 13 14 15 16 17 18 19 20
17 12 34  4 25  8 31 30 14 35

21 22 23 24 25 26 27 28 29 30
10 11  7 16 19 15 23 27  9 22

31 32 33 34 35
 2 28  5  6 26
-}
showBingo に (length x) を渡したけど、
(length (show n))を渡す方がよいかもです。
bingo(100)でも動作するようにしたつもり。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import random
import itertools

division = 10

def bingo(count):
    a = [i + 1 for i in xrange(count)]
    random.shuffle(a)
    width = len(str(count)) + 1
    it = ((i + 1, n) for (i, n) in enumerate(a))
    while 1:
        b = list(itertools.islice(it, division))
        if not b:
            break
        for i in xrange(2):
            print "".join(str(c[i]).rjust(width) for c in b)
        print

def main():
    bingo(30)
    bingo(35)

if __name__ == '__main__':
    main()
表示方法のみの変更なので show() 関数だけ変更
 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
BEGIN {
	srand
}

{
	n = $1

	bingo(n,ar)
	show(n,ar)
}

function show(n,ar, i,j,k,s1,s2)
{
	s1 = s2 = ""
	k = length(n)

	for (i=1; i<=n; i++) {
		s1 = s1 sprintf(" %"k"d", i+j)
		s2 = s2 sprintf(" %"k"d", ar[i+j])
		if (i % 10 == 0) {
			print s1
			print s2
			print ""
			s1 = s2 = ""
		}
	}
	if (s1 !~ /^$/) { # n % 10 > 0
		print s1
		print s2
		print ""
	}
}

function rand_between_1_and_n(n, x)
{
	x = 1 + int(rand * n)
	return (x <= n)? x : rand_between_1_and_n(n)
}

function bingo(n,ar,  i,x,y,t)
{
	delete ar;
	for (i=1; i<=n; i++) ar[i] = i

	for (i=n*2; i>0; i--) {
		x = rand_between_1_and_n(n)
		y = rand_between_1_and_n(n)
		if (x == y) continue

		t = ar[x] ; ar[x] = ar[y] ; ar[y] = t
	}
}
出力はこんな感じ
% awk -f bingo2.awk
5
 1 2 3 4 5
 1 4 5 2 3

10
  1  2  3  4  5  6  7  8  9 10
  3  8  2  7  1  5  4  9 10  6

15
  1  2  3  4  5  6  7  8  9 10
  9  5 13  2 15 14  6 11  4 12

 11 12 13 14 15
  8 10  3  1  7

19
  1  2  3  4  5  6  7  8  9 10
  5 11 10  1 12 15  3  7 17  9

 11 12 13 14 15 16 17 18 19
 19 18  8  6  2  4 16 14 13

20
  1  2  3  4  5  6  7  8  9 10
  1  4 10  9 14 20  3  6 18 19

 11 12 13 14 15 16 17 18 19 20
 17 15  8 16 13  5 12  2  7 11

21
  1  2  3  4  5  6  7  8  9 10
  5 16 11  4 10 15 18  2  1  9

 11 12 13 14 15 16 17 18 19 20
 19  7  6  8 13  3 12 14 21 17

 21
 20

30
  1  2  3  4  5  6  7  8  9 10
 21 26  7 24 23  5 17 10 16  9

 11 12 13 14 15 16 17 18 19 20
 11 20 12 30  1 14 18  4 15  6

 21 22 23 24 25 26 27 28 29 30
 22  8  3 25 28 19 27 29 13  2

100
   1   2   3   4   5   6   7   8   9  10
  55  98  44  13  99  81  53  61  56  87

  11  12  13  14  15  16  17  18  19  20
  82  24  52  92  66  51  18  70  19  58

  21  22  23  24  25  26  27  28  29  30
  41  47  39  43  94   8  80  59  42  79

  31  32  33  34  35  36  37  38  39  40
  27  73  36  12  62  37  83   9  54  96

  41  42  43  44  45  46  47  48  49  50
  69  84  45  17  26 100  50  67   6   1

  51  52  53  54  55  56  57  58  59  60
  15  65   4  33  16   5  78  23  74  75

  61  62  63  64  65  66  67  68  69  70
  63  38  40  28  91  89  72  34  77  35

  71  72  73  74  75  76  77  78  79  80
  11   2  21  30  49   3  71  57  25  31

  81  82  83  84  85  86  87  88  89  90
  14  10  93  60  85  90  46  88  48  32

  91  92  93  94  95  96  97  98  99 100
  22  95   7  68  29  20  64  97  86  76
bingo関数自体は#2255からいただきました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from random import shuffle

def bingo(n):
  l = range(1, n+1)
  shuffle(l)
  return l

def bingo_print(l):
  fmt = '%%%sd' % len(str(len(l)))
  a = range(1, len(l)+1)
  for i in range(0, len(l), 10):
    print ' '.join([fmt % j for j in a[i:i+10]])
    print ' '.join([fmt % j for j in l[i:i+10]]) + '\n'

bingo_print(bingo(30))
bingo_print(bingo(35))
出力データをまとめてprintしてみた。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from random import shuffle

def bingo(n):
  l = range(1, n+1)
  shuffle(l)
  return l

def bingo_print(l):
  fmt = '%%%sd' % len(str(len(l)))
  a = [fmt % i for i in range(1, len(l)+1)]
  b = [fmt % i for i in l]
  print '\n'.join(['%s\n%s\n' % (' '.join(a[i:i+10]), ' '.join(b[i:i+10])) for i in range(0, len(l), 10)])

bingo_print(bingo(30))
bingo_print(bingo(35))
僕が出題前に書いたコードはこんな感じですが、
確かに#2324みたいにrangeのstepを使った方がいいですね。
スライシングで添え字の範囲が超えてもエラーにならないので僕のコードの18行目以降みたいな
「1行に満たない残りがあれば表示」というコードがいらなくなるわけですね。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def bingo(n):
	from random import shuffle
	result = range(1, n + 1)
	shuffle(result)
	w = len(str(n))
	format = " %%%dd" % w
	nbuf = []
	rbuf = []
	for i in range(n):
		nbuf.append(format % (i + 1))
		rbuf.append(format % result[i])
		if i % 10 == 9:
			print "".join(nbuf)
			print "".join(rbuf)
			print
			nbuf = []
			rbuf = []
	if nbuf:
		print "".join(nbuf)
		print "".join(rbuf)

	
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#light
let rec bingo n = shuffle [1..n]
and  shuffle ls =
    let rnd = new System.Random()
    List.sort (fun x y-> rnd.Next(-1,2)) ls

let printLine ln n =
    let rec len (m:int) = ( m.ToString() ).Length
    and mk (m:int) = (String.make ((len n) - (len m)) ' ') ^ m.ToString()
    and (|SplitAt|) m xs = List.partition (fun (x,i) -> i <= m) xs
    and mkLns c = function
        | [] -> []
        | SplitAt c (head,tail) -> (List.unzip head)::mkLns (c+ln) tail
    and concatMap f xs = String.concat " " <| List.map f xs
    and bs = mkLns ln (List.zip (bingo n) [1..n])
    [for (xs,ids) in bs -> (concatMap mk xs) ^ "\n" ^ (concatMap mk ids)]
    |> String.concat "\n"
    |> printf "%s\n"

let bingoPr = fun n -> printLine 10 n
修正。
|> String.concat "\n"
じゃなくて
|> String.concat "\n\n"
としないとお題のようにならないですね。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import scala.util.Sorting.stableSort

def bingo(n:int) = {
  type PList = List[Pair[int,int]]
  val lst = stableSort[int,double](1 to n,x=>Math.random).zipWithIndex.toList
  val w = lst.size.toString.size+1
  def format(n:int) = String.format("%"+w+"d",Array(n.asInstanceOf[AnyRef]))

  def printline(x:PList) = {
    println(x.map(y=>format(y._2+1)).mkString(""))
    println(x.map(y=>format(y._1)).mkString("")+"\n")
  }

  def show(l:PList):unit = l.splitAt(10) match {
    case (l,Nil) => printline(l)
    case (l,ls) =>  printline(l);show(ls)
  }

  show(lst)
}

bingo(30)
bingo(35)
bingo関数自体が結果を出力していたので出力部分を変更。
リストに何番目かの値もInsertして出力してます。全然短くできず。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Public Sub bingo(ByVal n As Integer)
    Dim list As New List(Of Integer)
    For i As Integer = 1 To n
        list.Add(i)
    Next
    Dim r As New Random
    For i As Integer = 1 To n * 2
        Dim index As Integer = r.Next(0, n)
        list.Add(list(index))
        list.RemoveAt(index)
    Next

    For i As Integer = 0 To n - 1
        list.Insert((i \ 10) * 20 + i Mod 10, i + 1)
    Next

    For i As Integer = 1 To list.Count - 1
        Console.Write(list(i - 1).ToString.PadLeft(n.ToString.Length) & Space(-CInt(CBool(i Mod 10 <> 0))))
        If i Mod 10 = 0 OrElse i = list.Count - n Mod 10 Then
            Console.WriteLine(New String(ControlChars.Lf, -CInt(CBool(i Mod 20 = 0))))
        End If
    Next
    Console.WriteLine(list(list.Count - 1))
End Sub
ちょっとゴチャゴチャしてる。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import Random (randomRIO)
import Data.List ((\\),elemIndex)
import Data.Maybe (fromJust)
import Control.Monad (zipWithM_)

bingo :: Int -> IO [Int]
bingo n = b [1..n] n []
  where b [] n     ret = return ret 
        b xs (n+1) ret = do
          r <- randomRIO (0,n)
          let m = xs !! r in b (xs \\ [m]) n (ret ++ [m])

showBingo :: Int -> IO ()
showBingo n = bingo n >>= \xs -> zipWithM_ printBingo (f idxs) (f (t xs))
  where idxs = [1..n]
        f = map concat . map u . s 
        s xs = if xs == [] then [] else let (h,t) = splitAt 10 xs in h:s t
        t xs = map ((1+) . fromJust . (\x -> x `elemIndex` idxs)) xs
        u xs = let len = length (show n) in map (surpress (len + 1) . show) xs
        surpress n xs = reverse $ take n $ reverse xs ++ cycle " " 
        printBingo x y = putStrLn x >> putStrLn y >> putStrLn ""
Squeak Smalltalk で。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
| n size bingo streams |
n := 35.
size := n printString size + 1.
bingo := (1 to: n) asArray shuffled readStream.
streams := {String new writeStream. String new writeStream}.
World findATranscript: nil.
1 to: n do: [:idx |
	{idx. bingo next} with: streams do: [:int :strm |
		strm nextPutAll: (int printPaddedWith: $  to: size)].
	((idx isDivisibleBy: 10) or: [idx = n]) ifTrue: [
		Transcript cr.
		streams do: [:strm | Transcript cr; show: strm contents. strm reset]]]
シーケンスのshuffleはライブラリに追加しようかなあ。

今回のお題はshow-bingo関数で実装してます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
(use srfi-1)
(use srfi-27)
(use srfi-42)
(use gauche.sequence)
(use util.list)

(define (shuffle! seq)
  (do-ec (: n (- (size-of seq) 1) 0 -1)
         (let1 p (random-integer (+ n 1))
           (unless (= p n)
             (let1 tmp (ref seq n)
               (set! (ref seq n) (ref seq p))
               (set! (ref seq p) tmp)))))
  seq)

(define (bingo n)  (shuffle! (iota n 1)))

(define (show-bingo lis)
  (do-ec (: row (slices (zip (iota (length lis) 1) lis) 10))
         (begin
           (do-ec (: p row) (format #t "~3d" (car p))) (newline)
           (do-ec (: p row) (format #t "~3d" (cadr p))) (newline) (newline))))
 ブラウザとCScriptに対応。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Array.prototype.$huffle = function(){
  for(var $, r, i = this.length; i;)
    $ = this[r = Math.random() * i-- | 0], this[r] = this[i], this[i] = $;
  return this;
};
function bingo(n, w){
  if(!w) w = 10;
  for(var a = [], i = 1; i <= n;) a[a.length] = i++;
  var b = a.concat().$huffle(), r = [], l = (' '+ n).length;
  while(a.length) r[r.length] = a.splice(0, w).join(' ') +'\n'+ b.splice(0, w).join(' ');
  r = r.join('\n\n').replace(/ *\d+/g, function($){ while($.length < l) $ = ' '+ $; return $ });
  if(typeof WSH != 'undefined') WSH.stdOut.write(r);
  else document.write('<pre>'+ r +'</pre>');
}
ブックマークレット版: javascript:(function(n,w,a,b,r,l,i,$){for(a=[],l=('_'+n).length,i=0;i<n;a.push(++i));for(b=a.concat();n;$=b[i=Math.random()*n--|0],b[i]=b[n],b[n]=$);for(r=[];a.length;r.push(a.splice(0,w).join(' ')+'\n'+b.splice(0,w).join(' ')));return'<pre>'+r.join('\n\n').replace(/ *\d+/g,function($){while($.length<l)$=' '+$;return $})+'</pre>'})(35,10)

	
 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
33
34
using System;
using System.Text;
class Program
{
  static void Main()
  {
    PrintBingo(35);
  }
  static void PrintBingo(int n)
  {
    Random r = new Random();
    int[] a = new int[n];
    for (int i = 0; i < n; ++i) a[i] = i + 1;
    for (int i = n; i > 1; --i)
    {
      int k = r.Next(i);
      int tmp = a[i - 1];
      a[i - 1] = a[k];
      a[k] = tmp;
    }
    for (int i = 0; i < n; i++)
    {
      if (i % 10 == 0)
      {
        if (i > 0) Console.WriteLine("\n");
        for (int j = i; j < Math.Min(n, i + 10); j++)
          Console.Write("{0,3}", j + 1);
        Console.WriteLine();
      }
      Console.Write("{0,3}", a[i]);
    }
    Console.WriteLine();
  }
}
bingo関数自体#2289から少し変更しました。
(print-bingo (bingo 25))
 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
(defun bingo (n)
  (let ((*random-state* (make-random-state t)))
    (loop repeat n
          for rand = (loop 
                       (let ((rand (1+ (random n))))
                         (if (not (member rand lst))
                           (return rand))))
          collect rand into lst
          finally (return lst))))

(defun print-bingo (lst)
  (let ((index 0)
        (format-string (concatenate 
                         'string
                         "~{~"
                         (princ-to-string (1+ (length (princ-to-string (length lst)))))
                         "d~}~%" )))
    (loop for elements on lst by #'(lambda (x) (nthcdr 10 x))
          do (loop repeat 10
                   for e in elements
                   collect (incf index) into column-name
                   collect e into column-value
                   finally (format t format-string column-name)
                           (format t format-string column-value)
                           (terpri)))))
出力用の関数を追加。
ちょっとドロくさいかな?
 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
sub bingo($;)
{
    my $x = shift ;
    my @num = (1 .. $x);
    my $r;
    for( my $n = $x; $n>0; $n --)
    {
        $r = rand; $r *= 1000;
        push(@num, splice(@num, $r % $n, 1) );
    }
    return @num;
}

sub printTable(@)
{
    my @T = @_;
    my $N, $K;

    printf("[%d] => \n", $#T+1);
    for( $N=0; $N<=$#T; $N = $K + 1)
    {
        # 番号
        for( $K=$N; $K<$#T; $K ++ )
        {
            last if ($K-$N) >= 9;
            printf("%2d ", $K+1);
        }
        printf("%2d\n", $K+1);

        # 乱数
        for( $K=$N; $K<$#T; $K ++ )
        {
            last if ($K-$N) >= 9;
            printf("%2d ", $T[$K]);
        }
        printf("%2d\n", $T[$K]);

        printf("\n");
    }
}

my @table;

srand;
@table = bingo(30); ::printTable(@table);
@table = bingo(35); ::printTable(@table);

	
 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
<?php
function bingo($n){
	$a = range(1, $n);
	shuffle($a);
	
	return $a;
}

function show($a){
	$max = strlen(max($a));
	$html = array("<pre>\n");
	
	for($i=0; $i<count($a); $i+=10){
		for($j=$i, $number=$counter=array(); $j<$i+10; $j++){
			if($j>=count($a)) break;
			
			$counter[] = sprintf("% {$max}d", $j+1);
			$number[] = sprintf("% {$max}d", $a[$j]);
		}
		
		$html[] = sprintf("%s\n%s\n\n", join(" ", $counter), join(" ", $number));
	}
	
	$html[] = "</pre>";
	
	return join("", $html);
}

echo show(bingo(30));
echo show(bingo(35));
?>
10個ずつspliceすれば綺麗に書けると思ったんだけど、なんかごちゃごちゃしてしまった。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
use List::Util qw/shuffle/;
sub bingo {p(shuffle(1..$_[0]));}

sub p {
 my $i = 1;
 while(my @sublist = splice(@_,0,10)){
   for my $seq ($i..$i+scalar(@sublist)-1){printf "%3d", $seq;};
   print "\n";
   for my $num (@sublist){printf "%3d", $num;};
   print "\n\n";
   $i = $i + scalar(@sublist);
 }
}
あら、しまった。言語をperlにし忘れた。修正できん。
修正しました。
すいません、ありがとうございます。
混ざり具合は良くないですが(-_-
 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
#include <stdlib.h>

static int cmp(const void *p1, const void *p2)
{
    return (rand() % 2)?1:-1;
}

int *bingo(int num)
{
    int i, n;
    int *nums;

    if(num <= 0) return NULL;
    nums = (int*)malloc(sizeof(int) * num);
    for(i=0; i<num; i++){
        nums[i] = i + 1;
    }
    qsort(nums, num, sizeof(int), (int (*)(const void*, const void*))cmp);
    return nums;
}

void bingo_print(int *nums, int n)
{
    int i, j;
    for(i=0; i<n; i=j){
        for(j=i; j < n && (i == j || j % 10); j++)
            printf("%2d ", j + 1);
        printf("\n");
        for(j=i; j < n && (i == j || j % 10); j++)
            printf("%2d ", nums[j]);
        printf("\n\n");
    }
}

int main(int argc, char *argv[])
{
    int n;
    int *nums;
    if(argc < 2) return EXIT_FAILURE;
    n = atoi(argv[1]);
    srand(time(NULL));
    nums = bingo(n);
    bingo_print(nums, n);
    free(nums);
    return EXIT_SUCCESS;
}
bcc32とg++で確認。
 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cstdlib>

#ifdef _WIN32
# include <windows.h>
# define seed() ::GetCurrentTime()
#else
# include <ctime>
# define seed() std::time(NULL)
#endif

struct RandomGenerator
{
    RandomGenerator()
    {
        std::srand(static_cast<unsigned>(seed()));
    }

    int operator()(int n) const
    {
        const int i = static_cast<int>(static_cast<double>(std::rand()) * n / RAND_MAX);

        return std::max(0, std::min(i, n - 1));
    }
};

std::vector<size_t> create_bingo(size_t n)
{
    std::vector<size_t> v;

    for (size_t i = 0; i < n; ++i)
    {
        v.push_back(i);
    }

    static RandomGenerator gen;

    std::random_shuffle(v.begin(), v.end(), gen);

    return v;
}

void output(size_t value, size_t width)
{
    std::cout.width(width);

    std::cout << value;
}

size_t calculate_width(size_t value)
{
    size_t width = 1;

    for (; value >= 10; value /= 10)
    {
        ++width;
    }

    return width;
}

void bingo(size_t n)
{
    const std::vector<size_t> v = create_bingo(n);

    const size_t width = calculate_width(n) + 1;

    const size_t unit = 10;

    for (size_t beg = 0; beg < v.size(); beg += unit)
    {
        const size_t end = std::min(beg + unit, v.size());

        for (size_t i = beg; i < end; ++i)
        {
            output(i + 1, width);
        }

        std::cout << std::endl;

        for (size_t i = beg; i < end; ++i)
        {
            output(v[i], width);
        }

        std::cout << std::endl << std::endl;
    }
}

int main()
{
    bingo(30);
    bingo(35);
}
マニピュレータを使ってみた。
 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
33
34
35
36
37
38
39
--- main.orig   Fri Aug 24 13:50:54 2007
+++ main.cpp    Fri Aug 24 13:53:20 2007
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <iomanip>
 #include <vector>
 #include <algorithm>
 #include <iterator>
@@ -43,13 +44,6 @@
     return v;
 }

-void output(size_t value, size_t width)
-{
-    std::cout.width(width);
-
-    std::cout << value;
-}
-
 size_t calculate_width(size_t value)
 {
     size_t width = 1;
@@ -76,14 +70,14 @@

         for (size_t i = beg; i < end; ++i)
         {
-            output(i + 1, width);
+            std::cout << std::setw(width) << (i + 1);
         }

         std::cout << std::endl;

         for (size_t i = beg; i < end; ++i)
         {
-            output(v[i], width);
+            std::cout << std::setw(width) << v[i];
         }

         std::cout << std::endl << std::endl;
PS C:\>  format-bingo(bingo(5))
 1 2 3 4 5
 4 2 1 0 3
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
function bingo([int] $n)
{
     $r = new-object system.random
     $a = 0..($n-1)
     0..($n-1) | %{ $i = $r.next($n-1); $a[$_],$a[$i] = $a[$i],$a[$_] }
     $a
}

function format-bingo($ary)
{
     $keta = ([string]$ary.length).length + 1
     for ($i = 0; $i -lt $ary.length; $i+=10) {
          $len = $ary[($i)..($i+9)].length + $i
          [string]::join("", (@(($i+1)..$len) | %{"{0,$keta}" -f $_}))
          [string]::join("", ($ary[($i)..($len-1)] | %{"{0,$keta}" -f $_}))
          ""
     }
}

	
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
shuffle([], []).
shuffle(X, [R|Y]) :- length(X, XL), N is random(XL),
	nth0(N, X, R), select(R, X, X1), shuffle(X1, Y).

write_row(L, W) :- write_row(L, W, W).
write_row(   [], _,   _) :- nl.
write_row([X|L], W, Tab) :- format('~t~d~*|', [X, Tab]),
	Tab1 is Tab + W + 1, write_row(L, W, Tab1).

write_bingo(W, X, S) :-
	length(X, N), N > 10,
	nth0(10, X, XE), append(XL, [XE|XR], X),
	nth0(10, S, SE), append(SL, [SE|SR], S),
	write_row(XL, W), write_row(SL, W), nl,
	write_bingo(W, [XE|XR], [SE|SR]).
write_bingo(W, X, S) :- write_row(X, W), write_row(S, W).

bingo(N) :- findall(X, between(1, N, X), L), shuffle(L, S), 
	atom_number(A, N), atom_length(A, T), write_bingo(T, L, S).
perlで書いてみた
 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
33
sub bingo()
{
    my @array = ( 1 .. shift );
    my @out   = ();
    while ( my $x = splice( @array, int(rand(scalar @array)) , 1 ) )
    {
        push @out , $x ;
    }
    return [ @out ];
}

sub out()
{
    my @array = @{ $_[0] };
    my $i=1;
    while ( my @x = splice( @array, 0 , 10  )  )
    {
        my $n    = scalar @x ;
        my $comp = (int($i/$n)+1) * $n;
        while ( $i <= $comp )
        {
            printf "%3d", $i++;
        }
        print  "\n";
        while(my $a = shift @x )
        {
            printf "%3d" , $a ;
        }
        print  "\n\n";
    }
}

&out( &bingo(35) );
1行に10個とか,ラベルを付けてとか,空行を挟むとか言うことがなければ単に bingo <- sample でよいのだが。。。

> bingo(35)
 1  2  3  4  5  6  7  8  9 10 
28 30 18 14  8 15  9 29  4 19 

11 12 13 14 15 16 17 18 19 20 
16  2 21  3 22 24 27 26 31 13 

21 22 23 24 25 26 27 28 29 30 
34 11  7 20 23 25 33  5  1  6 

31 32 33 34 35 
17 35 10 32 12 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
bingo <- function(n) {
    m <- sample(n)
    names(m) <- 1:n
    for (i in 0:((n-1)%/%10)) {
        is <- i*10+1
        ie <- min(is+9, n)
        print(m[is:ie])
        cat("\n")
    }
}
表示桁指定は * でできますが、表示桁の求め方を 2 種類用意しました。
1. libm をリンクして、log10 を使う方法
2. stderr を捨てて fprintf を使う方法
 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
33
34
35
36
37
38
39
40
41
42
43
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
//#include <math.h>

void bingo( int n ){
   int tmp;
   int i,j;
   //int k = (int)log10( n )+1;
   int k = fprintf(stderr, "%d",n);
   int *deck = (int*)malloc(sizeof(int)*n);

   for( i = 0; i < n; i++ )
      deck[i] = i+1;

   for( i = 0; i < n; i++ ){
      j = rand() % (n-i);
      tmp = deck[j];
      deck[j] = deck[ n-i-1 ];
      deck[ n-i-1 ] = tmp;
   }

   for( i = 0; i < n; i+=10){
      for( j = i; j < i+10 && j < n; j++ )
         printf("%*d ", k, j+1 );
      printf("\n");
      for( j = i; j < i+10 && j < n; j++ )
         printf("%*d ", k, deck[j] );
      printf("\n");
      printf("\n");
   }

   free(deck);
}

int main ( void ){
   srand(time(NULL));
   bingo(9);
   printf("\n");
   bingo(23);
   printf("\n");
   return 0;
}

長くなってしまいましたが・・・

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ビンゴ(30)
●ビンゴ(n)
  bとは文字列
  cとは文字列
  nbとは整数=バイト数(n)
  //ビンゴを生成
  ビンゴ生成(n)を反復
      b=b&文字列右寄せ(対象,nb)&" "
  b=bを(nb+1)*10で行揃え
  //回数も生成
  iで1からnまで繰り返す
      c=c&文字列右寄せ(i,nb)&" "
  c=cを(nb+1)*10で行揃え
  //表示
  (切り上げ(n/10))回
      c[回数-1]を表示
      b[回数-1]を表示
      空を表示
●ビンゴ生成(n)
  rとは配列
  (n)回
    rに回数を配列追加
  rを配列シャッフル
  rで戻る

無理やり短く・・・

1
2
3
4
5
ビンゴ(30)
●ビンゴ(n)
  xとは整数=(文字数(n)+2);cとは配列;bとは配列;ビンゴ生成(n)で反復;b=b&文字列右寄(対象,x);c=c&文字列右寄(回数,x);もし(回数=n)ならば;b=行揃(b,(x*10));行揃(c,(x*10))で反復;表示(対象&改行&b[回数-1]&改行)
●ビンゴ生成(n)
  rとは配列;(n)回;配列追加(r,回数);もし(回数=n)ならば;戻(配列シャッフル(r))
 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    call srand tickcount;
    call bingo 35;
    endmacro;

bingo:
    ##i = 0;
    while( ##i < ##1 ) {
        ##dest[##i] = ##i + 1;
        ##i = ##i + 1;
    }
    ##i = 0;
    while( ##i < ##1 ) {
        call rand;
        ##r = ##return % ( ##1 - ##i ) + ##i;
        ##tmp = ##dest[##r];
        ##dest[##r] = ##dest[##i];
        ##dest[##i] = ##tmp;
        ##i = ##i + 1;
    }
    ##keta = strlen( str( ##1 ) );
    ##i = 0;
    while( ##i < ##1 ) {
        ##next = ##i + 10;
        if ( ##next > ##1 ) {
            ##next = ##1;
        }
        ##ii = ##i;
        while( ##ii < ##next ) {
            if ( ##ii > ##i ) {
                insert " ";
            }
            call KetaSoroe ##ii+1, ##keta;
            insert $$return;
            ##ii = ##ii + 1;
        }
        insert "\n";
        ##ii = ##i;
        while( ##ii < ##next ) {
            if ( ##ii > ##i ) {
                insert " ";
            }
            call KetaSoroe ##dest[##ii], ##keta;
            insert $$return;
            ##ii = ##ii + 1;
        }
        insert "\n\n";
        ##i = ##next;
    }
    return;

KetaSoroe:
    ##i = ##2 - strlen( str( ##1 ) );
    $$result = "";
    if ( ##i >= 0 ) {
        while( ##i > 0 ) {
            $$result = $$result + " ";
            ##i = ##i - 1;
        }
    }
    $$result = $$result + str( ##1 );
    return $$result;

rand:
    #rand_x = #rand_x * 214013 + 2531011;
    if ( #rand_x < 0 ) {
        return ( ( #rand_x + 1 ) / 65536 - 1 ) & 32767;
    }
    return #rand_x / 65536 & 32767;

srand:
    #rand_x = ##1;
    return;
 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
33
34
35
36
37
38
39
40
41
42
43
import std.random;
import std.stdio;
import std.string;

void show_bingo(int n, int[] xs) {
        int i;
        int j = cast(int)(toString(n).length);
        string s1;
        string s2;
        foreach (x; xs) {
                s1 ~= format("%*d ", j, i);
                s2 ~= format("%*d ", j, x);
                if (0 == (++i % 10)) {
                        writefln("%s\n%s\n", chop(s1), chop(s2));
                        s1 = s2 = "";
                }
        }
        if ("" != s1) {
                writefln("%s\n%s\n", chop(s1), chop(s2));
        }
}

void bingo(int n)
{
        int[] xs;
        for (int i = 1; i <= n; ++i) {
                xs ~= i;
        }
        for (int i = 0; i < n; ++i) {
                uint r = rand() % n;
                int tmp = xs[r];
                xs[r] = xs[i];
                xs[i] = tmp;
        }
        show_bingo(n, xs);
}

/*
void main() {
        bingo(30);
        bingo(35);
}
*/
formatでの整数指定がBなのに気がつかず、
ちょっと悩みました。
実数指定はC言語と同じくfなのに…。

1> c(show_bingo).
{ok,show_bingo}
2> show_bingo:bingo(30).
 1  2  3  4  5  6  7  8  9 10
23 19 12 14  2 13 29  7  1 26

11 12 13 14 15 16 17 18 19 20
 4  5 24 20 16  8 22 30  3 17

21 22 23 24 25 26 27 28 29 30
 6  9 18 25 15 21 28 11 27 10
ok
3> show_bingo:bingo(35).
 1  2  3  4  5  6  7  8  9 10
 5  2 21 29 10 33  4  7 20  6

11 12 13 14 15 16 17 18 19 20
34 30  3 16 24 22 23 12 18 14

21 22 23 24 25 26 27 28 29 30
17 28  9 15 26 13 11  8 27  1

31 32 33 34 35
25 35 32 19 31
ok
 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
33
-module(show_bingo).
-export([bingo/1]).

show_line([X | []], Size) -> io:format("~" ++ Size ++ "B~n", [X]);
show_line([X | XS], Size) ->
    io:format("~" ++ Size ++ "B ", [X]),
    show_line(XS, Size).

column_size(Num) ->
    Max = length(lists:last(io_lib:format("~B", [Num]))),
    lists:last(io_lib:format("~B", [Max])).

bingo_sub(Num) -> bingo_sub(lists:seq(1, Num), Num * Num).

bingo_sub(List, 0) -> List;
bingo_sub(List, Num) ->
    R = lists:nth(random:uniform(length(List)), List),
    bingo_sub([R] ++ [X || X <- List, X =/= R], Num - 1).

bingo(Num) -> bingo(bingo_sub(Num), lists:seq(1, Num), column_size(Num)).

bingo([], _, _) -> true;
bingo(Rnd, Seq, Size) ->
    if
        length(Rnd) > 10 ->
            show_line(lists:sublist(Seq, 10), Size),
            show_line(lists:sublist(Rnd, 10), Size),
            io:nl(),
            bingo(lists:nthtail(10, Rnd), lists:nthtail(10, Seq), Size);
        true ->
            show_line(Seq, Size),
            show_line(Rnd, Size)
    end.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
(* bingo定義はhttp://ja.doukaku.org/comment/5033/ *)
let (%%) x y = (x/y*y=x) ;;

let print_bingo arr = 
  let times = Array.length arr in
  let iter last x y f =
    (for i = x to (min last y) do (f i) done) in
  
  let pr = Printf.printf "%3d" in
  let nl = print_newline in
  
  let print_turn n x =
    if (x%%n) then (
      nl(); nl();
      iter times (x+1) (x+n) (pr);
      nl();
    );
  in
  Array.iteri (fun i x -> print_turn 10 i; pr x) arr;;

print_bingo (bingo 35);;

特にありません.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
N = 22
def put_bingo(n, col)
  d = n.to_s.size + 1
  index = Array.new(n){|i| i+1}
  bingo = Array.new(n){|i| index.delete_at(rand(n-i).modulo(n-i))}.
    map{|x| sprintf("% #{d}d", x)} #bingoの結果を生成
  (n.div(col) + 1).times{|i|
    size = bingo.size
    index = Array.new(size >= col ? col : size){|j| sprintf("% #{d}d", i*10+j+1)}.join
    result = bingo.slice!(0..(size >= col ? 9 : -1)).join
    puts "#{index}\n#{result}\n\n" if result.size > 0
  }
end
put_bingo(N, 10) #引数はbingoの大きさと出力時の列数の2つ
#5208 同様、dmd 2.009 ではコンパイルできません。
 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
33
34
35
import std.stdio;
import std.random;
import std.string;

void bingo(uint n){
    uint[] a;
    a.length = n;
    foreach(i, ref e; a){
        e = i + 1;
    }
    randomShuffle(a, Random(unpredictableSeed()));

    uint max = 10;

    string[] indexBuf, randBuf;
    int numWidth = toString(n).length;
    foreach(i, e; a){
        indexBuf ~= format("%*d", numWidth, i + 1);
        randBuf ~= format("%*d", numWidth, e);
        if((i + 1) % max == 0 || i == a.length - 1){
            writeln(indexBuf.join(" "));
            writeln(randBuf.join(" "));
            if(i != a.length - 1){
                writeln();
            }
            indexBuf.length = randBuf.length = 0;
        }
    }
}

void main(){
    bingo(30);
    writeln("----");
    bingo(35);
}
「重複無し乱数」で投稿したものを手直ししました。そろそろバッチでできることの限界
が見えてきたような気がします。

  e.g.
    C:\>bingo 30
      1  2  3  4  5  6  7  8  9 10
      6 14  2 13  4 28 20  9 12 16

     11 12 13 14 15 16 17 18 19 20
     26 15  1 30 21 25 27 22 19 29
    
     21 22 23 24 25 26 27 28 29 30
      3 23 10 24  5 18 11 17  7  8

    C:\>bingo 35
      1  2  3  4  5  6  7  8  9 10
     10 24 34 13  2 25 17 14  8 30

     11 12 13 14 15 16 17 18 19 20
     29 12 23 20 18 31  9  6 27 11

     21 22 23 24 25 26 27 28 29 30
     33  5 35  1 15 21  3 32 26 22

     31 32 33 34 35
     28  7 19 16  4

遅延環境変数展開を利用しているので、Windows NTでは動作しません。Windows XPで動作
を確認。
 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
:: bingo.bat
@echo off
  setlocal enabledelayedexpansion
    set C=10
    set i=0
    set j=0
    set k=0
    set l=0
    set m=0
    set s=
    set t=
    set v=0

    echo %1|findstr /r "[^0-9]" >NUL 2>&1
    if %ERRORLEVEL% equ 0 (echo %~n0 [NUMBER] & goto :EOF)

    if %1 equ 0 goto :EOF

    :: 擬似配列を生成
    for /l %%i in (1,1,%1) do set v_%%i=%%i

    :: 値をシャッフル
    call :length %1 l
    echo set j=%%RANDOM:~-%l%%%>_.bat
    set i=1
    :shuffle
      ::  8進数として解釈されないよう 0を加算
      call _.bat & set /a j+=0
      set /a j=%j%%%%1+1
      set v=!v_%i%!
      set v_%i%=!v_%j%!
      set v_%j%=%v%
      set /a i+=1
    if %i% lss %1 goto shuffle
    del _.bat

    :: 結果を整形表示
    set /a i=%1/%C%
    set /a m=%1%%%C%
    if %m% gtr 0 set /a i+=1
    set j=1
    set k=%C%
    if %1 lss %C% set k=%1

    for /l %%i in (1,1,%i%) do (
      :: 上段
      set s=
      for /l %%j in (!j!,1,!k!) do (
        set t=%%j
        if %%j lss %1 call :lpad !t! %l% t
        set s=!s!!t!
        if %%j lss !k! set s=!s! 
      )
      echo  !s!

      :: 下段
      set s=
      for /l %%j in (!j!,1,!k!) do (
        set t=
        call :lpad !v_%%j! %l% t
        set s=!s!!t!
        if %%j lss !k! set s=!s! 
      )
      echo  !s!

      if %%i lss %i% echo.

      set /a j+=%C%
      set /a k+=%C%
      if !k! gtr %1 set k=%1
    )
  endlocal
goto :EOF

:lpad
  setlocal enabledelayedexpansion
    set l=0
    set t=

    call :length %1 l
    set /a l=%2-%l%
    for /l %%i in (1,1,%l%) do set t=!t! 
  endlocal & set %3=%t%%1
goto :EOF

:length
  setlocal
    set i=0
    set t=%1
    set t=%t:"=%

    :loop
      set t=%t:~1%
      set /a i+=1
    if not "%t%" == "" goto loop
  endlocal & set %2=%i%
goto :EOF
   bingo2 7
 1 2 3 4 5 6 7
 2 1 4 3 7 5 6

   bingo2 17
  1  2  3  4  5  6  7  8  9 10
 14  7  3  9 15 17 10 16  1  4

 11 12 13 14 15 16 17         
  5  8  2 12 11 13  6         
1
bingo2=:3 :'_10(>:#":y.)&":&|:\>:(i.,.?~)y.'

率直に言ってgroupByを使うべきケースでしょうこれは。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def bingo(n) {
   (1..n).toList().sort{ Math.random() }
}

def bingoprint(n) {
  def bingo = bingo(n)
  (1..n).groupBy{(it-1).intdiv(10)}.each{k,v->
    v.each{printf "%3d",it};println()
    v.each{printf "%3d",bingo[it-1]};println("\n")
  }
}

bingoprint(30)
bingoprint(35)

Index

Feed

Other

Link

Pathtraq

loading...