challenge 文字列で+を表示する

与えられた文字列で+のかたちを表示するプログラムをかいてください。
サンプル入力:
doukaku

サンプル出力:
       doukakud
       u      o
       k      u
       a      k
       k      a
       u      k
       o      u
doukakud      doukakud
u                    o
k                    u
a                    k
k                    a
u                    k
o                    u
dukakuod      dukakuod
       u      o
       k      u
       a      k
       k      a
       u      k
       o      u
       dukakuod

Posted feedbacks - Nested

Flatten Hidden

こういうことかしら?

 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
using System;
using System.Linq;

class Program {
    static void Main(string[] args) {
        string loop = args[0] + args[0][0];
        string reverse = new string(loop.ToCharArray().Reverse().ToArray());

        Console.WriteLine(new string(' ', args[0].Length) + loop);

        hoge(args[0]);

        Console.WriteLine(loop + new string(' ', args[0].Length - 1) + loop);

        for(int i = 0; i < args[0].Length - 1; i++) {
            Console.WriteLine(args[0][args[0].Length - (i + 1)] + new string(' ', args[0].Length * 3 - 1) + args[0][i + 1]);
        }

        Console.WriteLine(reverse + new string(' ', args[0].Length - 1) + reverse);

        hoge(args[0]);

        Console.WriteLine(new string(' ', args[0].Length) + reverse);
    }

    private static void hoge(string arg) {
        for(int i = 0; i < arg.Length - 1; i++) {
            Console.WriteLine(new string(' ', arg.Length) + arg[arg.Length - (i + 1)] + new string(' ', arg.Length - 1) + arg[i + 1]);
        }
    }
}

めっちゃベタに書いてしまった。 長さ1の文字列を与えられた時の例外処理もしてません。

 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
{
    j = 1;
    rev = "";
    l = length($0);
    for(i = 1; i <= l; i++){
        ch[i] = substr($0, i, 1);
    }
    for(i = l; i > 0; i--){
        rev = rev ch[i];
    }
    line[j++] = sprintf("%*s%s%c", l, " ", $0, ch[1]);
    for(i = 2; i <= l; i++){
        line[j++] = sprintf("%*s%c%*s%c", l, " ", ch[l - i + 2], l - 1, " ", ch[i]);
    }
    line[j++] = sprintf("%s%c%*s%s%c", $0, ch[1], l - 1, " ", $0, ch[1]);
    for(i = 2; i <= l; i++){
        line[j++] = sprintf("%c%*s%c", ch[l - i + 2], l * 3 - 1, " ", ch[i]);
    }
    line[j++] = sprintf("%c%s%*s%c%s", ch[1], rev, l - 1, " ", ch[1], rev);
    for(i = 2; i <= l; i++){
        line[j++] = sprintf("%*s%c%*s%c", l, " ", ch[l - i + 2], l - 1, " ", ch[i]);
    }
    line[j++] = sprintf("%*s%c%s", l, " ", ch[1], rev);
    for(i = 1; i < j; i++){
        print line[i];
    }
}
座標計算めんどくさいです
 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
use strict;
use warnings;

if (!@ARGV || length($ARGV[0]) < 2) {
    print "usage: $0 <any word(more than 2-chars)>\n";
    exit 0;
}

my $w = shift;
my $l = length($w);
my $ll = $l * 3 + 1;
my $c = (' ' x $ll . "\n") x $ll;

my @w = split //, $w;
for my $i (0 .. $l-1) {
    substr($c, $l+$i, 1) =
    substr($c, ($ll+1)*$l+$i, 1) =
    substr($c, ($ll+1)*$l+($l*2)+$i, 1) =
    substr($c, ($ll+1)*$l*2+$l-$i, 1) =
    substr($c, ($ll+1)*$l*2+($l*3)-$i, 1) =
    substr($c, -2 - $l - $i, 1) =
    substr($c, ($ll+1)*$i+$l*2, 1) =
    substr($c, ($ll+1)*($l+$i)+$l*3, 1) =
    substr($c, ($ll+1)*($l*2+$i)+$l*2, 1) = 
    substr($c, ($ll+1)*($l*3-$i)+$l, 1 ) = 
    substr($c, ($ll+1)*($l*2-$i), 1) = 
    substr($c, ($ll+1)*($l-$i)+$l, 1) = $w[$i];
}

print $c;

LOGO風に

 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
type NextTurnDirection =
    |Right
    |Left
let cdr (dx,dy) = ((-1)*dy,dx) //cdrはchangeDirectionRightの略
let cdl (dx,dy) = (dy,(-1)*dx) //cdlはchangeDirectionLeftの略

let doWork (s:string) =
    let len = s.Length
    let canvasArr = Array2D.create (3*len + 1) (3*len + 1) ' ' 
    let startPos = (len,0)
    let getNextTrunDirection turnN = 
        if turnN % 3 = 1 then Left else Right //3回に1回左折
    let rec drawCanvas stepNum turnNum (x,y) (dx,dy) cbfvosp =
       // cbfvospはcanBeFirstVisitOnStartPointの略
       if (x,y) = startPos && cbfvosp = false then
            ()
       else
          canvasArr.[x,y] <- s.[stepNum] 
          match (stepNum,turnNum) with
          |(sn,tn)  when sn = len - 1 && (getNextTrunDirection tn) = Right
                ->  drawCanvas 0 (tn + 1) (x+dx,y+dy) (cdr (dx,dy)) false
          |(sn,tn)  when sn = len - 1 && (getNextTrunDirection tn) = Left
                ->  drawCanvas 0 (tn + 1) (x+dx,y+dy) (cdl (dx,dy)) false   
          |(sn,tn)
                ->  drawCanvas (stepNum+1) tn (x+dx,y+dy) (dx,dy) false
    drawCanvas 0 0  startPos (1,0) true  
    for i in 0 .. 3*len do
        printfn ""
        for j in 0 .. 3*len do
            printf "%c" canvasArr.[j,i]

open System

[<STAThread()>] 
[<EntryPoint>] 
let main(args) = 
    if (args.Length = 0 || args.[0].Length <2) then
        printf "引数が不正です。"
    else
        doWork args.[0]
    0

表示範囲毎に条件式をまとめました. 条件式をまとめることのできる部分はまとめようと頑張りましたが,途中で諦めてしまいました.ですのでこんなに条件文が長いwww

 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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( int argc, char *argv[] )
{
    if( argc != 2 ) {
        fprintf( stderr, "usage: %s string\n", argv[0] );
        exit( EXIT_FAILURE );
    }

    int length = strlen( argv[1] );  /* get length of input string */
    int i, j;
    for( j = 0; j <= length * 3; j++ ) {
        for( i = 0; i <= length * 3; i++ ) {
            /* region A */
            if( j == 0 && 
                length <= i && i <= length * 2 - 1 ) 
                printf( "%c", argv[1][ i - length  ] );
            /* region B, region F */
            else if( i == length * 2 &&
                     ( ( 0 <= j && j <= length - 1 ) || ( length * 2 <= j && j <= length * 3 - 1 ) ) )
                printf( "%c", argv[1][j - ( j / ( length * 2 ) ) * length * 2] );
            /* region C */
            else if( j == length &&
                     length * 2 <= i && i <= length * 3 - 1 )
                printf( "%c", argv[1][i - length * 2] );
            /* region D */
            else if( i == length * 3 &&
                     length <= j && j <= length * 2 - 1 )
                printf( "%c", argv[1][j - length] );
            /* region E */
            else if( j == length * 2 &&
                     length * 2 + 1 <= i && i <= length * 3 )
                printf( "%c", argv[1][length * 3 - i ] );
            /* region G */
            else if( j == length * 3 &&
                     length + 1 <= i && i <= length * 2 )
                printf( "%c", argv[1][ length * 2 - i] );
            /* region H */
            else if( i == length &&
                     length * 2 + 1 <= j && j <= length * length * 3 )
                printf( "%c", argv[1][ length * 3 - j ] );
            /* region I */
            else if( j == length * 2 &&
                     1 <= i && i <= length )
                printf( "%c", argv[1][length - i] );
            /* region J */
            else if( i == 0 &&
                     length + 1 <= j && j <= length * 2 )
                printf( "%c", argv[1][length * 2 - j] );
            /* region K */
            else if( j == length &&
                     0 <= i && i <= length - 1 )
                printf( "%c", argv[1][i] );
            /* region L */
            else if( i == length &&
                     1 <= j && j <= length )
                printf( "%c", argv[1][length - j ] );
            else
                printf( " " );
        }
        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
25
26
27
public class Doukaku {
    public static void main(String[] args) {
        String s = "doukaku";
        int len = s.length();
        for (int r = 0; r <= len * 3; r++) {
            for (int c = 0; c <= len * 3; c++) {
                System.out.print(getChar(r, c, s));
            }
            System.out.println();
        }
    }
    
    static char getChar(int r, int c, String s) {
        int l0 = 0, l1 = s.length(), l2 = l1 * 2, l3 = l1 * 3;
        boolean cc = c > l1 && c < l2, rr = r > l1 && r < l2;
        return r == l0 &&  cc || r == l1 && !cc ? charAt(s, c, false)
             : r == l2 && !cc || r == l3 &&  cc ? charAt(s, c, true)
             : c == l0 &&  rr || c == l1 && !rr ? charAt(s, r, true)
             : c == l2 && !rr || c == l3 &&  rr ? charAt(s, r, false)
             : ' ';
    }
    
    static char charAt(String s, int i, boolean rev) {
        return s.charAt((rev ? s.length() * 3 - i : i) % s.length());
    }

}

Cらしく、ポインタテーブルで...

 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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void outputs(char *input_word)
{
    int unit = strlen(input_word);
    int rows = unit * 3 + 1, cols = unit * 3 + 2;
    int table_size = rows * cols;
    char ** const table = malloc(sizeof(char*) * rows + sizeof(char) * table_size);
    int ptr_table_size = (unit * 3) * 4;
    char ** const ptr_table = malloc(sizeof(char*) * ptr_table_size);
    int index = 0;
    int i, j;

    for(i = 0; i < rows; i++) /* 初期化 */
        table[i] = (char*)(table + rows) + i * cols;

    for(i = 0; i < rows; table[i][j] = '\0' ,i++)
        for(j = 0; j < cols - 1; j++)
            table[i][j] = ' ';

#define SLIDE_IF_ODD_(x)        ((x) / unit % 2 ? unit : 0)
    for(i = 0; i < rows - 1; index++, i++){ /* 下準備 */
        ptr_table[index]                      = &table[i    ][unit * 2 + SLIDE_IF_ODD_(i)];
        ptr_table[ptr_table_size - 1 - index] = &table[i + 1][unit     - SLIDE_IF_ODD_(i)];
    }

    for(j = 0; j < cols - 2; index++, j++){
        ptr_table[index]                      = &table[unit     - SLIDE_IF_ODD_(j)][j    ];
        ptr_table[ptr_table_size - 1 - index] = &table[unit * 2 + SLIDE_IF_ODD_(j)][j + 1];
    }
#undef SLIDE_IF_ODD_

    for(i = 0; i < ptr_table_size; i++) /* 書き込み */
        *ptr_table[i] = *(input_word + i % unit);

    for(i = 0; i < rows; i++) /* 出力 */
        puts(table[i]);

    free(table);
    free(ptr_table);
}

int main(int argc, char **argv)
{
    char buf[BUFSIZ];

    puts("Input a word:");

    if(fgets(buf, _countof(buf), stdin)){
        int length = strlen(buf);

        if(buf[length - 1] == '\n'){
            buf[length - 1] = '\0';
            outputs(buf);
        }
    }

    return 0;
}

Squeak Smalltalk で。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
| str map up down left right pos |
str := 'doukaku'.

up := (down := 1 @ 0) negated.
left := (right := 0 @ 1) negated.
map := Matrix new: str size * 3 + 1 element: Character space.

pos := 1 @ str size + right.
{right. down. right. down. left. down. left. up. left. up. right. up} do: [:direction |
    str do: [:chr | map at: pos x at: pos y put: chr. pos := pos + direction]].

World findATranscript: nil.
(1 to: map rowCount) do: [:nrow |
    Transcript cr; show: ('', (map atRow: nrow)) withoutTrailingBlanks]
もっとFunctionalに書きたいのですが…。
  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
 98
 99
100
101
102
103
104
105
class Cross(val src: String) {

  // 角の凹みの数
  val dent = 1

  // 格子の数
  val grid = dent * 2 + 1

  // 一辺の長さ
  val side = src.length * grid + 1

  // 描画エリア
  val area:Array[Array[char]] = 
    for (row <- ((" " * side +"\n") * side).split("\n"))
      yield row.toCharArray

  // 水平描画が右向き:true/左向き:false
  var hAhead = true

  // 垂直描画が下向き:true/上向き:false
  var vAhead = true

  // 描画開始位置と描画方向を表現するクラス。
  case class Direction(val posX: Int, val posY: Int, val heading: Int)

  // 最初の描画位置、上段、中央の格子から、水平:右向きに描画する。
  val start = Direction(grid / 2, 0, Cross.HeadingRight)

  // 描画開始
  write(start)

  // 描画メソッド
  def write(d: Direction) :Unit = {
    val x = d.posX * src.length
    val y = d.posY * src.length
    
    d.heading match {
      case Cross.HeadingRight =>
       for (i <- x to x + src.length -1) {
         area(y)(i) = src.charAt(i - x)
       }
      case Cross.HeadingBottom =>
       for (i <- y to y + src.length -1) {
         area(i)(x) = src.charAt(i - y)
       }
      case Cross.HeadingLeft =>
       for (i <- (x- src.length + 1 to x).reverse) {
         area(y)(i) = src.charAt(x - i)
       }
      case Cross.HeadingTop =>
       for (i <- (y - src.length +1 to y).reverse) {
         area(i)(x) = src.charAt(y - i)
       }
    }
    var next = this.next(d) 
    if (next != start) {
      write(next)
    }
  }

  // 次の描画開始位置と描画方向を返す。
  def next(d:Direction) = {
    d.heading match {
      case Cross.HeadingRight =>
       if (d.posX + 2 > grid)
         hAhead = false
       Direction(d.posX + 1, d.posY, if (vAhead) Cross.HeadingBottom else Cross.HeadingTop )
      case Cross.HeadingBottom =>
       if (d.posY + 2 > grid)
         vAhead = false
       Direction(d.posX, d.posY + 1, if (hAhead) Cross.HeadingRight else Cross.HeadingLeft)
      case Cross.HeadingLeft =>
       if (d.posX - 2 < 0 )
         hAhead = true
       Direction(d.posX - 1, d.posY, if (vAhead) Cross.HeadingBottom else Cross.HeadingTop)
      case Cross.HeadingTop =>
       if (d.posY - 2 < 0 )
         vAhead = true
       Direction(d.posX, d.posY - 1, if (hAhead) Cross.HeadingRight else Cross.HeadingLeft)
    }
  }

  // コンソールに表示する。
  def show {
    for(row <- area)
      println(new String(row))
  }
}


object Cross {
  val HeadingRight = 0 
  val HeadingBottom = 1
  val HeadingLeft = 2  
  val HeadingTop = 3   
}

object RunCross {
  def main(args: Array[String]): Unit = {
    val src = if (args.length >= 1) args(0) else "doukaku"
    val cross = new Cross(src)
    cross.show
    
  }
}
   f '123'
   1231
   3  2
   2  3
1231  1231
3        2
2        3
1321  1321
   3  2
   2  3
   1231
   
   f 'world'
     worldw
     d    o
     l    r
     r    l
     o    d
worldw    worldw
d              o
l              r
r              l
o              d
wdlrow    wdlrow
     d    o
     l    r
     r    l
     o    d
     worldw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
f=:3 :0
   P=.{.y
   TB=.,.}.y
   BT=.,.|.TB
   EL=.<:#y
   SP=.' '
   a=.y,P,(EL#SP),y,P
   smoutput ((,~#y)$SP),.(y,P),BT,.((,~EL)$SP),.TB
   smoutput (a,BT,.((EL,<:3*#y)$SP),.TB),|.a
   smoutput ((,~#y)$SP),.(BT,.((,~EL)$SP),.TB),y,P
)
 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 <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>

struct point
{
    int x;
    int y;

    point& operator += (const point& other)
    {
        x += other.x;
        y += other.y;
        return *this;
    }
};

static const point vs[] =
{
    {  1,  0 }, {  0,  1 }, {  1,  0 }, {  0,  1 },
    { -1,  0 }, {  0,  1 }, { -1,  0 }, {  0, -1 },
    { -1,  0 }, {  0, -1 }, {  1,  0 }, {  0, -1 }
};

void doukaku291(const std::string& s)
{
    std::vector<std::string> v(s.size() * 3 + 1, std::string(s.size() * 3 + 1, ' '));
    point p = { s.size(), 0 };
    for(int i = 0; i < 12; ++i)
    {
        for(std::string::const_iterator it = s.begin(); it != s.end(); ++it)
        {
            v[p.y][p.x] = *it;
            p += vs[i];
        }
    }
    std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(std::cout, "¥n"));
}

int main(int argc, char* argv[])
{
    doukaku291("doukaku");

    return 0;
}

ちょっと…かなり?…ブサイクかなぁ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
doukaku291 s = 
  mapM_ (\(row, cols) -> putStrLn $ map (\col -> ch col row) cols) field
    where
      right = ( 1,  0)
      left  = (-1,  0)
      down  = ( 0,  1)
      up    = ( 0, -1)

      ds   = [ right, down, right, down, left, down, left, up, left, up, right, up ]
      ss   = concat $ map (\(s, d) -> zip (repeat d) s) $ zip (repeat s) ds
      line = toLine (length s, 0) ss
        where
          toLine _ [] = []
          toLine (sx, sy) (((x, y), c):ds) = ((sx, sy), c):(toLine (sx + x, sy + y) ds)

      field = zip [0..] $ replicate ((length s) * 3 + 1) $ take ((length s) * 3 + 1) [0..]

      ch row col = case lookup (col, row) line of
                     Just c  -> c
                     Nothing -> ' '

main = doukaku291 "doukaku"

最初にこんなリストを作って,

("   abc    "
 "          "
 "          "
 "abc   abc "
 "          "
 "          "
 "          "
 "          "
 "          "
 "          ")

90°ずつ回転させたのと合わせました。

   abca
   c  b
   b  c
abca  abca
c        b
b        c
acba  acba
   c  b
   b  c
   acba
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(defun rotate (m) (apply #'map 'list #'vector (reverse m)))

(defun merge-line (&rest lines)
  (apply #'map 'string
         (lambda (&rest chars)
           (or (find #\Space chars :test #'char/=)
               #\Space))
         lines))

(defun merge-matrix (&rest matrices)
  (apply #'mapcar #'merge-line matrices))

(defun write-cross (s)
  (let* ((m (let* ((n (length s))
                   (empty (format nil "~V@T~V@T~V@T " n n n))
                   (line1 (format nil "~V@T~A~V@T " n s n))
                   (line2 (format nil "~A~V@T~A " s n s)))
              `(,line1 ,@(make-list (1- n) :initial-element empty)
                ,line2 ,@(make-list (* 2 n) :initial-element empty))))
         (m1 (rotate m))
         (m2 (rotate m1))
         (m3 (rotate m2)))
    (mapc #'write-line (merge-matrix m m1 m2 m3))))
#10105に感銘。Haskellで再現させてみました。
quarterが1/4。
quarterとquarterの上下左右を入れ替えたものの合成がhalf。
rot90halfがhalfを90度回転させたもの。
halfとrot90halfの合成が最終結果。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
doukaku291 s = zipWith (\x y -> zipWith max x y) half rot90Half
  where
    ss n      = replicate n ' '
    len       = length s
    width     = len * 3 + 1
    quartar   = [(ss len) ++ s ++ (ss len) ++ " "] ++
                (replicate (len - 1) $ ss width)   ++
                [s ++ (ss len) ++ s ++ " "]        ++
                replicate (len * 2) (ss width)
    half      = zipWith max quartar $ reverse $ map (\x -> reverse x) quartar
    rot90Half = reverse $ take width $ foldr rot (replicate width []) half
      where rot (c:cs) (r:rs) = (c:r):(rot cs rs)

main = mapM_ putStrLn $ doukaku291 "doukaku"

Lost_dogです。この前はログインするの忘れましたが、今回は大丈夫です。

この問題をあえて汎用的にするならば、コンソール画面に方向を指定してテキストを描画するっていう感じかなーということで書きました。コードは若干長くなりましたけど、やってることは単純なので。。

STArrayとかの使い方は、参考ページを見ながら書きました。

STArrayを使ったら、なんか型が意味不明になってきて、これにIOとかRandomとか入ってきたら、なにがなんだか。。そこは上手に分離してコーディングしろっていうことなのかな・・・

配列を更新する処理は、やっぱハスケラーにとっては歯がゆいところなのかなぁ・・・

 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
module Canvas where
import Control.Monad.ST
import Data.Array.ST
import Data.Array

main = putStrLn $ unlines $ map (dropWhileR (==' ')) 
       $ splitsAt (3*n+1) $ elems $ runST $ showPlus xs 
  where xs = "doukaku"
        n  = length xs

data Direction = Up | Down | Left | Right deriving Eq

showPlus xs = let n = length xs in do 
  a <- newArray ((0,0),(3*n,3*n)) ' ' :: ST s (STArray s (Int,Int) Char)
  writeText a (0,n)     Canvas.Right xs
  writeText a (0,2*n)   Canvas.Down  xs
  writeText a (n,2*n)   Canvas.Right xs
  writeText a (n,3*n)   Canvas.Down  xs
  writeText a (2*n,3*n) Canvas.Left  xs
  writeText a (2*n,2*n) Canvas.Down  xs
  writeText a (3*n,2*n) Canvas.Left  xs
  writeText a (3*n,n)   Canvas.Up    xs
  writeText a (2*n,n)   Canvas.Left  xs
  writeText a (2*n,0)   Canvas.Up    xs
  writeText a (n,0)     Canvas.Right xs
  writeText a (n,n)     Canvas.Up    xs
  freeze a

writeText _ (_,_) _ []     = return ()
writeText a (x,y) d (t:ts) = do
  r <- getBounds a
  if inRange r (x,y) 
    then do writeArray a (x,y) t 
            case d of
              Canvas.Up    -> writeText a (pred x,y) d ts
              Canvas.Down  -> writeText a (succ x,y) d ts
              Canvas.Left  -> writeText a (x,pred y) d ts
              Canvas.Right -> writeText a (x,succ y) d ts
    else return ()

dropWhileR p = reverse.dropWhile p.reverse

splitsAt n [] = []
splitsAt n xs = ys : splitsAt n zs where (ys,zs) = splitAt n xs
図形の作り方に多少汎用性を持たせてみました。

結果:
        dounano?d        
        ?       o        
        o       u        
        n       n        
        a       a        
        n       n        
        u       o        
        o       ?        
dounano?d       dounano?d
?                       o
o                       u
n                       n
a                       a
n                       n
u                       o
o                       ?
d?onanuod       d?onanuod
        ?       o        
        o       u        
        n       n        
        a       a        
        n       n        
        u       o        
        o       ?        
        d?onanuod        
 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
object StringShape {
    def main(args : Array[String]) : Unit = {
         val target = "dounano?"
        val mover =
            P(1,0) ::
            P(0,1) ::
            P(1,0) ::
            P(0,1) ::
            P(-1,0) ::
            P(0,1) ::
            P(-1,0) ::
            P(0,-1) ::
            P(-1,0) ::
            P(0,-1) ::
            P(1,0) ::
            P(0,-1) ::
            Nil
        val da = new DrawingArea
        var x, y = 0
        mover.foreach { m =>
            target.foreach { c =>
                  da += (P(x,y),c)
                x += m.x
                y += m.y
            }
        }
         for (y <- da.y_min to da.y_max) {
             for (x <- da.x_min to da.x_max) print(da(P(x,y)))
             println()
         }
    }

     case class P(val x:Int, val y:Int)
    class DrawingArea {
        var x_min, y_min, x_max, y_max = 0
        private val area:scala.collection.mutable.Map[P,Char] = new scala.collection.mutable.HashMap()
        def +=(point:P, c:Char) = {
            area += ((point, c))
            x_min = x_min.min(point.x)
            y_min = y_min.min(point.y)
            x_max = x_max.max(point.x)
            y_max = y_max.max(point.y)
        }
        def apply(point:P):Char = {
            area.getOrElse(point,' ')
        }
    }
}

pythonがまだだったので投稿。

最初に、board = [" " * max] * max とやったらshalow copyだったためにはまったのは良い思い出・・・。

 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
import sys

if len(sys.argv) < 2 or len(sys.argv[1]) < 2:
    print "Usage:doukaku291 word(more than 2-chars)"
    exit(0)

w = sys.argv[1]
l = len(w)
max = l * 3 + 1
board = [[" " for i in xrange(max)] for j in xrange(max)]

ds = [
    (1, 0), (0, 1), (1, 0), (0, 1),
    (-1, 0), (0, 1), (-1, 0), (0, -1),
    (-1, 0), (0, -1), (1, 0), (0, -1),
]

(x, y) = (l, 0)
for d in ds:
    for s in w:
        board[y][x] = s
        (x, y) = (x + d[0], y + d[1])

for line in board:
    print "".join(line)
文字数チェックはしてないです。
 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
type CyclicString(s : string) =
  let len = s.Length
  let mutable c = -1
  member this.Item(n : int) = s.[n % len]
  member this.Length = len
  member this.get() = 
    c <- if c + 1 = len then 0 else c + 1
    this.[c]

type Char2d(xSize, ySize) =
  let ch2d = Array2D.create xSize ySize ' '
  let mutable _pos = (0, 0)
  member this.pos
    with get() = _pos
    and  set(p) = _pos <- p
  member this.put ch =
    let (x, y) = _pos
    ch2d.[x,y] <- ch
  member this.printOut() = 
    for y = 0 to ySize - 1 do
      for x = 0 to xSize - 1 do
        printf "%c" ch2d.[x, y]
      printfn ""

let cross (str) =
   let up    pos = (fst pos, snd pos - 1)
   let down  pos = (fst pos, snd pos + 1)
   let left  pos = (fst pos - 1, snd pos)
   let right pos = (fst pos + 1, snd pos)
   let command = seq [right; up; right; down; right; down; left; down; left; up; left; up]
   let cs = CyclicString(str)
   let len = cs.Length
   let ch2d = Char2d(len * 3 + 1, len * 3 + 1)
   ch2d.pos <- (0, len)

   let interpreter f =
     for i = 1 to len do
       ch2d.put <| cs.get()
       ch2d.pos <- f ch2d.pos

   Seq.iter interpreter command
   ch2d.printOut()

do cross "doukaku"
せっかくなので動きをつけてみました
(BetweenAS3を使ってみたかっただけとも言う)
  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
 98
 99
100
101
102
103
104
105
106
107
108
package {
  import flash.display.Sprite;
  import flash.text.TextField;
  import flash.text.TextFieldType;
  import flash.text.TextFieldAutoSize;
  import flash.events.MouseEvent;
  import org.libspark.betweenas3.BetweenAS3;
  import org.libspark.betweenas3.tweens.ITween;
  import org.libspark.betweenas3.easing.Cubic;
  import org.libspark.betweenas3.events.TweenEvent;

  [SWF(backgroundColor="#ffffff")]
  public class Doukaku291 extends Sprite {
    private var inputArea:TextField;
    private var button:TextField;
    private var chars:Vector.<TextField>;

    private const DIRECTIONS:Array = [
      { x : 1, y : 0 },
      { x : 0, y : 1 },
      { x : 1, y : 0 },
      { x : 0, y : 1 },
      { x : -1, y : 0 },
      { x : 0, y : 1 },
      { x : -1, y : 0 },
      { x : 0, y : -1 },
      { x : -1, y : 0 },
      { x : 0, y : -1 },
      { x : 1, y : 0 },
      { x : 0, y : -1 }
    ];

    public function Doukaku291() {
      inputArea = new TextField();
      inputArea.border = true;
      inputArea.multiline = false;
      inputArea.type = TextFieldType.INPUT;
      inputArea.width = 150;
      inputArea.height = inputArea.textHeight + 5;
      inputArea.x = 20;
      inputArea.y = 10;
      stage.addChild(inputArea);
      
      button = new TextField();
      button.text = "start";
      button.border = true;
      button.background = true;
      button.backgroundColor = 0xffccaa;
      button.autoSize = TextFieldAutoSize.CENTER;
      button.height = inputArea.textHeight + 5;
      button.x = inputArea.x + inputArea.width + 10;
      button.y = inputArea.y;
      stage.addChild(button);

      chars = new Vector.<TextField>();
      button.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
          drawString(inputArea.text,
            stage.stageWidth / 2, inputArea.y + inputArea.height + 10);
        });
    }

    private function drawString(str:String, posX:int, posY:int):void {
      var i:int, c:String;
      var tmp:TextField;
      var strArray:Array = str.split("");
      var tween:ITween;
      var tweens:Array = new Array();

      for (i = 0; i < chars.length; i++) {
        stage.removeChild(chars[i]);
      }
      chars = new Vector.<TextField>();

      for (i = 0; i < 12; i++) {
        for each (c in strArray) {
          tmp = new TextField();
          tmp.text = c;
          tmp.height = tmp.textHeight;
          tmp.width = tmp.textWidth;
          tmp.autoSize = TextFieldAutoSize.CENTER;
          chars.push(tmp);
        }
      }

      chars[0].x = posX;
      chars[0].y = posY;
      stage.addChild(chars[0]);
      for (i = 1; i < chars.length; i++) {
        chars[i].visible = false;
        stage.addChild(chars[i]);
        chars[i].x = chars[i - 1].x + chars[i - 1].width * DIRECTIONS[int((i - 1) / strArray.length)].x;
        chars[i].y = chars[i - 1].y + chars[i - 1].height * DIRECTIONS[int((i - 1) / strArray.length)].y;

        tween = BetweenAS3.tween(chars[i],
          { x : chars[i].x, y : chars[i].y },
          { x : chars[i - 1].x, y : chars[i - 1].y },
          0.1, Cubic.easeOut);

        tween.addEventListener(TweenEvent.UPDATE, function(e:TweenEvent):void {
            e.target.target.visible = true
          });
        tweens.push(tween);
      }

      BetweenAS3.serialTweens(tweens).play();
    }
  }
}

久しぶりに投稿します。関数型言語といえばfold。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
let printPlus = function
    | null | "" -> ()
    | str ->
        let len = String.length str
        let moves = [(1, 0); (0, 1); (1, 0); (0, 1); (-1, 0); (0, 1);
                     (-1, 0); (0, -1); (-1, 0); (0, -1); (1, 0); (0, -1)]
        let plot map (x, y) (dx, dy) =
            ((map, (x, y)), str) ||> Seq.fold (fun (m, (x', y')) c ->
                (Map.add (x', y') c m, (x' + dx, y' + dy)))
        let plots =
            ((Map.empty, (len, 0)), moves) ||> List.fold (fun (m, xy) mv -> plot m xy mv)
            |> fst
        [for y in 0 .. (len * 3) ->
            [for x in 0 .. (len * 3) ->
                match Map.tryFind (x, y) plots with Some(c) -> string c | None -> " "]
            |> String.concat ""]
        |> List.iter (printfn "%s")

printPlus "doukaku"
Python の勉強の一環として取り組んでみました。
□や◇その他の形状にも柔軟に対応できる(無駄な)汎用性がウリです。
 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
class Canvas:

    __canvas = []

    def __init__(self, width, length):
        for y in range(0, length):
            self.__canvas.append([' '] * width)
        
    __x = 0
    __y = 0
    def point(self, x, y):
        self.__x = x
        self.__y = y

    def draw(self, string, direction):
        for char in string:
            self.__canvas[self.__y][self.__x] = char
            self.__x += direction[0]
            self.__y += direction[1]

    def p(self):
        for row in self.__canvas:
            print ''.join(row)
            
class Direction:
    north = [0, -1]
    northEast = [1, -1]
    east = [1, 0]
    southEast = [1, 1]
    south = [0, 1]
    southWest = [-1, 1]
    west = [-1, 0]
    northWest = [-1, -1]

def drawCross(string):
    canvas = Canvas(len(string)*3+1, len(string)*3+1)
    canvas.point(len(string), 0)

    directions = (
        Direction.east,
        Direction.south,
        Direction.east,
        Direction.south,
        Direction.west,
        Direction.south,
        Direction.west,
        Direction.north,
        Direction.west,
        Direction.north,
        Direction.east,
        Direction.north)

    for d in directions:
        canvas.draw(string, d)
    canvas.p()
    
drawCross('doukaku')

方向指示を三角関数で求めるように改造。それにしても何て冗長な数式だい。

 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
import math

class Canvas:

    __canvas = []

    def __init__(self, width, length):
        for y in range(0, length):
            self.__canvas.append([' '] * width)
        
    __x = 0
    __y = 0
    def point(self, x, y):
        self.__x = x
        self.__y = y

    def draw(self, string, direction):
        for char in string:
            self.__canvas[self.__y][self.__x] = char
            self.__x += direction[0]
            self.__y += direction[1]

    def get(self):
        return self.__canvas

    def p(self):
        for row in self.__canvas:
            print ''.join(row)

def direction(i):
    return (int(2 * (0.25 + 0.25 * math.sin(math.pi * (2 * i + 5) / 2)) * math.copysign(1, (math.sin(math.pi * (2 * i + 5) / 2 / 6)))),
    int(2 * (0.25 + 0.25 * math.sin(math.pi * (2 * i - 1) / 2)) * math.copysign(1, (math.sin(math.pi * (2 * i - 1) / 2 / 6)))))

def drawCross(string):
    canvas = Canvas(len(string)*3+1, len(string)*3+1)
    canvas.point(len(string), 0)
    for i in range(0, 12):
        canvas.draw(string, direction(i))
    canvas.p()
    
drawCross('doukaku')

批評いただければ幸いです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Edge = $*[0]
Direction = [:right, :down, :right, :down, :left, :down, :left, :up, :left, :up, :right, :up]
Screen, @x, @y = [[]], 0, 0

def right; Edge.each_char {|c| Screen[@y][@x] = c; @x += 1} end
def down; Edge.each_char {|c| Screen[@y][@x] = c; @y += 1; Screen[@y] ||= []} end
def left; Edge.each_char {|c| Screen[@y][@x] = c; @x -= 1; (@x = 0; Screen.map{|l| l.unshift(nil)}) if @x == -1} end
def up; Edge.each_char {|c| Screen[@y][@x] = c; @y -= 1; (@y = 0; Screen.unshift([])) if @y == -1} end
Direction.each {|d| send d}
Screen.each {|l| puts l.map {|c| c || ' '}.join}
絶対値と割り算を使って座標値からハンドルの切り具合を計算します。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import Maybe

putStrCross s = mapM_ putStrLn [[fromMaybe ' ' $ lookup (i,j) cs| i <- rng]| j <- rng] where
  (m, m3, rng) = (length s, 3*m, [0..m3])
  cs = zip (cross (m,m) (1,0)) $ concat $ replicate 12 s
  cross (x,y) (dx,dy) = (x,y): cross (x+dx',y+dy') (dx',dy') where
    (s,t) = ((abs (2*x-m3) +  abs(2*y-m3) - m3) `quot` m, 1 - abs s)
    (dx',dy') = (t*dx - s*dy, s*dx + t*dy)
{-
> putStrCross "doukaku"
-}
#10273を見て、ifはMaybeにすればいいのかと思い実装。考え方は#10116(#10105)。
それだけでは芸がないので、ラムダやlet, where節等を使わずに書くとどうなるかやってみた。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
module Main where

import Data.List
import Data.Maybe (fromMaybe)
import Control.Monad (mplus)
import Control.Applicative ((<*>))

genCross = map (fromMaybe ' ')
       . foldr (zipWith mplus) (repeat Nothing)
       . map (>>= (++ [Just '\n']))
       . take 4
       . iterate (reverse . transpose)
       . map (++ [Nothing])
       . ((++) . id <*> (replicate . (* 2) . pred . length <*> (`replicate` Nothing) . length . head))
       . foldr1 (zipWith (++))
       . ((:) . reverse <*> ((:) . id <*> (: []) . reverse))
       . ((:) . map Just <*> (replicate <*> (`replicate` Nothing)) . length)

main = putStrLn . genCross $ "doukaku"

はじめまして。 Golfと違って高階関数を使えるのがウレシイ。 ふつうにハンドルを切ってます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import Data.List

r [x,y] = [-y, x]
l [x,y] = [ y,-x]

ds = scanr id [0,1] [r,r,l,r,r,l,r,r,l,r,r]

place str = snd $ mapAccumL phi [len,len] [ (d, ch) | d<-ds, ch<-str ]
  where phi pos (d, ch) = (zipWith (+) pos d, (pos, ch))
        len = length str

cross str = unlines [ [ maybe ' ' id $ lookup [x,y] $ place str | y<-is ] | x<-is ]
  where is = [0..3*length str]

main = putStrLn . cross =<< getLine
言語選ぶの忘れてた‥orz 削除できないのかなぁ。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import Data.List

r [x,y] = [-y, x]
l [x,y] = [ y,-x]

ds = scanr id [0,1] [r,r,l,r,r,l,r,r,l,r,r]

place str = snd $ mapAccumL phi [len,len] [ (d, ch) | d<-ds, ch<-str ]
  where phi pos (d, ch) = (zipWith (+) pos d, (pos, ch))
        len = length str

cross str = unlines [ [ maybe ' ' id $ lookup [x,y] $ place str | y<-is ] | x<-is ]
  where is = [0..3*length str]

main = putStrLn . cross =<< getLine
clojure に挑戦してみました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
(defn plus [st]
  (let [len (.length st)
        line-w (inc (* len 3))
        coll (apply concat
               (interleave
                 (partition len (range 1 line-w))
                 (list (repeat len len)(repeat len (* len 2))'())))
        coll-y (concat (repeat (inc len) 0) coll
                 (repeat (dec len) (* len 3))(reverse coll))
        coll-x (apply concat (reverse (split-at (* len 3) coll-y)))
        matrix (map (fn [x y] (vector x y)) coll-x coll-y)
        str-12 (apply concat (repeat 12 (seq st)))
        ms-map (apply hash-map (interleave matrix str-12))]
    (apply str
      (map #(apply str %)
        (interpose "\n"
          (partition (inc line-w)
            (for [y (range 0 line-w) x (range 0 (inc line-w))]
              (format "%s" (get ms-map (vector x y) " ")))))))))

(println (plus "doukaku"))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
s = ARGV.shift || "doukaku"

w = s.length * 3 + 1
f = ((" " * w + "\n") * w).split("\n")
x, y, dx, dy = s.length, 0, 0, -1
([:R, :R, :L].collect { |p| [p] + s.split(//) } * 4).flatten.each { |c|
  dx, dy        = -dy, dx           if c == :R
  dx, dy        = dy, -dx           if c == :L
  f[y][x], x, y = c, x + dx, y + dy if c.kind_of? String
}
print f.join("\n"), "\n"
タートルグラフィックで描いてみました。
ちなみに、斜めに描くこともできます。(^^;
              d             d
             u o           u o
            k   u         k   u
           a     k       a     k
          k       a     k       a
         u         k   u         k
        o           u o           u
       d             d             d
        u                         o
         k                       u
          a                     k
           k                   a
            u                 k
             o               u
              d             d
             u               o
            k                 u
           a                   k
          k                     a
         u                       k
        o                         u
       d             d             d
        u           o u           o
         k         u   k         u
          a       k     a       k
           k     a       k     a
            u   k         u   k
             o u           o u
              d             d
 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
/** キャンバス */
class Canvas(val sizeX:Int, val sizeY:Int) {
    var canvas:Array[StringBuffer] = 
        (for(i <- 0 until sizeY) yield new StringBuffer(" "*sizeX)).toArray
    def set(x:Int, y:Int, ch:Char):Unit = {
        if (0 <= y && y < sizeY && 0 <= x && x < sizeX)
            canvas(y).setCharAt(x, ch)
    }
    override def toString():String = canvas.mkString("\n")
}

/** タートル・グラフィック(^^; */
class Turtle(c:Canvas) {
    var canvas:Canvas = c
    var x:Double = 0.0        // 左上が原点
    var y:Double = 0.0        // 左上が原点
    var th:Double = 0.0        // radian 北が0で右回りが正
    /** 右に t[radian]向く */
    def turn(t:Double):Unit = {
        th += t
    }
    /** 前に進む */
    def go(text:String):Unit = {
        for (i <- 0 until text.length) {
            canvas.set(x.asInstanceOf[Int], y.asInstanceOf[Int], text.charAt(i))
            x += Math.round(Math.sin(th)).asInstanceOf[Int]
            y += Math.round(-Math.cos(th)).asInstanceOf[Int]
        }
    }
    /** 指定位置に進む */
    def setPos(newX:Double, newY:Double):Unit = {
        x = newX
        y = newY
    }
}

/** 文字列で+を表示する */
object Doukaku {
    def main(args:Array[String]):Unit = {
        var canvas = new Canvas(50, 50)        // 固定。多めに取っている
        var turtle = new Turtle(canvas)

        val text = if (args.length > 0) args(0) else "doukaku"

        turtle.setPos(text.length, 0)
        turtle.turn(Math.Pi / 2)

//        turtle.setPos(text.length, 10)    // 斜めに表示する場合は前の2行をコメントにし、
//        turtle.turn(Math.Pi / 3)        // この2行をコメントアウトしてください。

        turtle.go(text)
        turtle.turn(Math.Pi / 2)
        turtle.go(text)
        turtle.turn(-Math.Pi / 2)
        turtle.go(text)
        turtle.turn(Math.Pi / 2)
        turtle.go(text)
        turtle.turn(Math.Pi / 2)
        turtle.go(text)
        turtle.turn(-Math.Pi / 2)
        turtle.go(text)
        turtle.turn(Math.Pi / 2)
        turtle.go(text)
        turtle.turn(Math.Pi / 2)
        turtle.go(text)
        turtle.turn(-Math.Pi / 2)
        turtle.go(text)
        turtle.turn(Math.Pi / 2)
        turtle.go(text)
        turtle.turn(Math.Pi / 2)
        turtle.go(text)
        turtle.turn(-Math.Pi / 2)
        turtle.go(text)

        println(canvas)
    }
}

2次元配列をつくる →1文字ずつ埋める →つなげる →(゚Д゚)ウマー

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function plusStr (s) {
    var s = String (s) || 'doukaku', l = s.length, r = s.split ('').reverse ().join (''), a = [];
    /*下向きに埋める*/
    a.down = function ([x, y], s) {
        for (var i = 0 ; i < l; i++) {
            if (! a[x + i]) a[x + i] = Array (3 * l + 1).join (' ').split ('');
            this[x + i][y] = s[i];
        }
    };
    [[0, 2 * l], [l, 3 * l], [2 * l, 2 * l]].forEach (function (v) {a.down (v, s)});
    [[1, l], [l + 1, 0], [2 * l + 1, l]].forEach (function (v) {a.down (v, r)});
    /*横向きに埋める*/
    a.right = function ([x, y], s) {
        for (var i = 0 ; i < l; i++){
            this[x][y + i] = s[i];
        }
    };
    [[0, l], [l, 0], [l, 2 * l]].forEach (function (v) {a.right (v, s)});
    [[2 * l, 1], [2 * l, 2 * l + 1], [3 * l, l + 1]].forEach (function (v) {a.right (v, r)});
    /*繋げる*/
    return a.map (function (b) {return b.join ('').replace(/ +$/, '')}).join ("\n");
}
console.log (plusStr ('koukaku'));

#10263が興味深い方法なので、すこし変更してみました。 ・class化 ・ちょっとだけタートルグラフィックの真似("rrl"部分を"rrlrl"とか"rrllr"などに変えてみて下さい)

 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
class Moji2zukei
  def initialize(edge)
    @Screen, @x, @y, @edge, @dx, @dy = [[]], 0, 0, edge, 1,0
  end
  
  def r; @dx, @dy = -@dy, @dx; zset; end
  def l; @dx, @dy = @dy, -@dx; zset; end

  def zset
    @edge.each_char {|c|
      @Screen[@y][@x] = c;
      @x += @dx; @y += @dy
      @Screen[@y] ||= []
      (@x = 0; @Screen.map{|l| l.unshift(nil)}) if @x == -1
      (@y = 0; @Screen.unshift([])) if @y == -1
    }
  end

  def scrout
    @Screen.each {|l| puts l.map {|c| c || ' '}.join}
  end
end

Direction = "rrl".split("").map{|x|x.to_sym}*4
m2z = Moji2zukei.new($*[0])
Direction.each {|d| m2z.send d}
m2z.scrout

Index

Feed

Other

Link

Pathtraq

loading...