文字列で+を表示する
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]
|
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とか入ってきたら、なにがなんだか。。そこは上手に分離してコーディングしろっていうことなのかな・・・
配列を更新する処理は、やっぱハスケラーにとっては歯がゆいところなのかなぁ・・・
see: Haskell/Hierarchical libraries/Arrays
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を使ってみたかっただけとも言う)
see: 文字列で+を表示する | wonderfl build flash online
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
|
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
|
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
|






pooq
#10078()
Rating3/3=1.00
与えられた文字列で+のかたちを表示するプログラムをかいてください。 サンプル入力: 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[ reply ]