challenge 与えられた文字列でピラミッド

ピラミッドを作る」の続編です。 与えられた文字列を使って下の例のようなピラミッドを書いてください。 頂点は与えられた文字列の最後の一文字、 底辺は与えられた文字列の各文字の間に空白が入ったものになります。
>>> pyramid("hoge")
   e   
  g e  
 o g e 
h o g e
>>> pyramid("abracadabra")
          a          
         r a         
        b r a        
       a b r a       
      d a b r a      
     a d a b r a     
    c a d a b r a    
   a c a d a b r a   
  r a c a d a b r a  
 b r a c a d a b r a 
a b r a c a d a b r a

Posted feedbacks - Nested

Flatten Hidden
末尾の空白の数がサンプル出力と違いますが、題意になかったのでスルーしました。

chainは引数のイテレータを順番に実行するイテレータを返す関数です。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
pyramid: fun(str) {
    space: [" "].cycle;
    arr: str.split("").to_a;
    n: arr.length;
    n.times.map(|i| i + 1){
        chain(space.take(n - it ),
              arr.slice(n - it, n).zip(space).map(|a,b| a~b)).join("").p;
    }
}

pyramid("hoge");
pyramid("abracadabra");
文字を1文字づつ配列にするメソッドがあるのかどうかわからないので作りました。
Sequence split は 引数をあたえないと空白でわけるようです。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Sequence splitEvery := method(
    l := list()
    self foreach(v, 
        l append(v asCharacter)
    )   
    return l
)
pyramid := method(str,
    t := str size * 2 - 1 
    for(i, 1, str size,
        str slice(str size - i, str size) splitEvery join(" ") alignCenter(t, " ") println 
    )   
)

	
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
String.prototype.repeat = function(n) {
    for(var i=0, str=""; i < n; i++) {
        str += this;
    }
    return str;
}

String.prototype.alignCenter = function(n, str) {
    var r = (n - this.length) / 2;
    return str.repeat(r) + this + str.repeat(r);
}

var pyramid = function(str) {
    var t = str.length * 2 - 1
    var res = ""
    for(var i=1, len=str.length; i<=len; i++) {
        res += str.slice(str.length - i, str.length).split("").join(" ").alignCenter(t, " ") + "\n"
    }
    return res;
}
String.alignCenter を修正
1
2
3
4
String.prototype.alignCenter = function(n, str) {
    var r = (n - this.length) / 2
    return str.repeat(Math.floor(r)) + this + str.repeat(Math.ceil(r));
}
瞬殺
1
str="abracadabra"; (str.length-1).downto(0) {|i| print(" "*i, str[i..-1].split(//).join(" "),"\n") }
Rubyに対する対抗意識w
1
s="abracadabra";n=len(s);print"\n".join(" ".join(s[~i:]).center(n*2-1)for i in range(n))
キモいコードでごめんなさい。
1
2
3
4
5
6
7
sub pyramid {
    my $i = my @py = split //, $_[0];
    print ' ' x $i . "@py[$i..$#py]\n" while $i--;
}

pyramid('hoge');
pyramid('abracadabra');

	
1
2
3
4
5
6
7
8
9
function pyramid(str)
  len = string.len(str)
  for i=len, 1, -1 do
    io.stdout:write(string.rep(" ",i-1))
    for j=i, len, 1 do io.stdout:write(string.sub(str,j,j), " ") end
    io.stdout:write("\n")
  end
end
pyramid("abracadabra")
Scheme用SLIMEがあればいいのに…
1
2
3
4
5
6
7
8
(use srfi-1)
(define (pyramid str)
  (map
   (lambda (i)
     (format #t "~a~a~%" (make-string i)
             (string-join (map string (string->list str i (string-length str))) " ")))
   (iota (- (string-length str) 0) (- (string-length str) 1) -1)))
(pyramid "abracadabra")
文字列のインデックスアクセスも算術演算も明示的ループも無しで。
1
2
3
4
5
6
(use util.list)
(define (pyramid s)
  (let r ((s (string->list s)) (p '()))
    (unless (null? s)
      (r (cdr s) (cons #\ p))
      (apply print (append p (intersperse #\  s))))))
名前付きletは明示的loopじゃないと?:)
名前付けてるだけだも〜ん。 それにいわゆる「ループとしての使いかた」はしてないし。
Never mind ! :)
loop以外で部分文字列の取り方がわからんorz
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(defun pyramid (str)
  (loop for i from (1- (length str)) downto 0 do
       (format t "~a~a~%"
               (make-string i :initial-element #\Space)
               (apply #'concatenate 'string
                      (loop for c across str
                         for j from 0
                         when (<= i j)
                         collect (format nil "~c~a" c " "))))))
(pyramid "abracadabra")
>部分文字列の取り方
subseq です?

	
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <stdio.h>

void pyramid(char *str) {
    int i,j,len;
    len = strlen(str);
    for (i=len-1; i>=0; i--) {
        for(j=0; j<i; j++) printf(" ");
        for(j=i; j<len; j++) printf("%c%c", str[j], ' ');
        printf("\n");
    }
}

int main() {
    pyramid("abracadabra");
    return 0;
}
C書いた直後にDを書くと、文字列の扱いを混同してしまった
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
private import std.stdio;

void pyramid(char[] str) {
    int i,j;
    for (i=str.length-1; i>=0; i--) {
        for(j=0; j<i; j++) writef(" ");
        for(j=i; j<str.length; j++) writef("%s%s", str[j], " ");
        writef("\n");
    }
}

int main() {
    pyramid("abracadabra");
    return 0;
}

	
1
2
3
4
5
6
7
8
(require 'cl)
(defun pyramid (str)
  (interactive "sPyramid string: ")
  (with-output-to-temp-buffer "*Pyramid*"
    (loop for i from (1- (length str)) downto 0 do
          (princ (make-string i ? ))
          (princ (mapconcat 'identity (split-string (substring str i) "") " "))
          (terpri))))
Cと変わらねえww
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function pyramid () {
    str=$1
    len=`expr length $str`
    for ((i=$len; i>=1; i--)); do
        for ((j=0; j<$i; j++)); do echo -n ' '; done
        for ((j=$i; j<=$len; j++)); do
            echo -n `expr substr $str $j 1`' '
        done
        echo
    done
}
pyramid "abracadabra"
明示的算術演算なし版。自分では再帰も書かない版です。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import Data.List

binapp o f g x = f x `o` g x
pyramid = binapp (zipWith (++)) (map (map (const ' ')) . tail . tails)
                                (map (intersperse ' ') . tail . inits)
printPyramid = putStr . unlines . pyramid

{-
*Main> printPyramid "abracadabra"
          a
         a b
        a b r
       a b r a
      a b r a c
     a b r a c a
    a b r a c a d
   a b r a c a d a
  a b r a c a d a b
 a b r a c a d a b r
a b r a c a d a b r a
-}
だめじゃんこれ、題意を読み違えてる。
題意を読み違えてたので再投稿
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Data.List

binapp o f g x = f x `o` g x
pyramid = binapp (zipWith (++)) (map (map (const ' ')) . tail)
                                (map (intersperse ' ') . tail . reverse)
        . tails
printPyramid = putStr . unlines . pyramid

{-
*Main> printPyramid "abracadabra"
          a
         r a
        b r a
       a b r a
      d a b r a
     a d a b r a
    c a d a b r a
   a c a d a b r a
  r a c a d a b r a
 b r a c a d a b r a
a b r a c a d a b r a
-}
% awk -f pyramid.awk hogehogehoge
           e 
          g e 
         o g e 
        h o g e 
       e h o g e 
      g e h o g e 
     o g e h o g e 
    h o g e h o g e 
   e h o g e h o g e 
  g e h o g e h o g e 
 o g e h o g e h o g e 
h o g e h o g e h o g e 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
BEGIN {
	if (length(ARGV[1]) > 0) printf pyramid(ARGV[1])
}

function pyramid(str,  N,moji,i,j)
{
	N = split(str,moji,"")

	s = ""
	a = moji[1]; for (i=2; i<=N; i++) a = a " " moji[i]  ## a = moji.join(' ')
	for (i=N; i>=1; i--) {
		s = a "\n" s
		sub(/[a-z]/,"",a)  ## 先頭から1文字ずつ消していく
	}
	return s
}

	
1
2
3
4
5
6
def pyramid(s):
	for i in range(len(s)):
		print ' '.join(s[~i:]).center(len(s)*2-1)

pyramid('hoge')
pyramid('abracadabra')

	
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
function pyramid($data) {
	$stclm = strlen($data);
	for ( $i = strlen($data) - 1; $i > -1; $i-- ) {
		$stclm--;
		echo str_pad("",$stclm," ",STR_PAD_LEFT);
		for ( $j = $i; $j < strlen($data); $j++ ) {
			echo substr($data,$j,1)." ";
		}
		echo "\n";
	}
}

pyramid("hoge");
pyramid("abracadabra");
?>

	
1
2
3
4
5
6
def pyramid(s:String) = {
  val (len, cs) = (s.size-1, s.toList)
  len.until(-1,-1).map(cs.splitAt).foreach{p =>
    println((p._1.map(x=>""):::p._2).mkString(" "))
  }
}

	
 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
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>

void pyramid(const std::string& s)
{
    for (std::string::const_iterator it = s.end(); it != s.begin(); --it)
    {
        const size_t n = std::distance(s.begin(), it - 1);

        std::fill_n(std::ostream_iterator<char>(std::cout), n, ' ');

        std::copy(it - 1, s.end() - 1, std::ostream_iterator<char>(std::cout, " "));

        std::cout << *(s.end() - 1);

        std::fill_n(std::ostream_iterator<char>(std::cout), n, ' ');

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

int main()
{
    pyramid("hoge");
    pyramid("abracadabra");
}
まとめてprint
1
2
3
4
5
def pyramid(s):
  print '\n'.join([' '*i + ' '.join(s[i:]) for i in range(len(s)-1, -1, -1)]),

pyramid('hoge')
pyramid('abracadabra')
phpって変な関数いっぱいあるな。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function pyramid($str) {
    $splt;
    for ($i = 0; $i < strlen($str); $i++) {
        $s = str_split(substr($str,$i,strlen($str)));
        $splt[] = str_repeat(" ", $i) .join(" ",$s);
    }
    krsort($splt);
    return join("\n",$splt);
}
echo pyramid("abracadabra");
上記は英語のみ。
日本語混ざると死にます。
 シンプルに。

javascript:(function(p,r,m,d){for(p=p.split(''),r=[],m=p.length,d=0;m--;p[d++]='')r[m]=p.join(' ');return'<pre>'+r.join('\n')+'</pre>'})('abracadabra')
1
2
3
4
5
function pyramid(s){
  s = s.split('');
  for(var r = [], i = s.length, j = 0; i--; s[j++] = "") r[i] = s.join(' ');
  return r.join('\n');
}
Squeak Smalltalk で。
1
2
3
4
5
6
| input |
input := 'abracadabra'.
World findATranscript: nil.
1 to: input size do: [:len |
	Transcript cr; show: (String new: input size - len withAll: $ ).
	(input last: len) do: [:each | Transcript show: each] separatedBy: [Transcript space]]

	
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Pyramid {
	public static void main(String[] args) {
		String data = args.length > 0 ? args[0] : "abracatabra";
		char[] spaceChars = new char[data.length()-1];
		java.util.Arrays.fill(spaceChars, ' ');
		String space = new String(spaceChars);
		
		for(int i=0;i<data.length();i++) {
			System.out.println(space.substring(i)
					+ data.substring(data.length()-1-i).replaceAll("(.)(?=.)","$1 "));
		}
	}
}
お、phpの投稿が増えてる。
ということで私なりに…。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php
function pyramid($str)
{
    $len=strlen($str);
    $str=implode(" ",str_split($str));
    for($i=1;$i<=$len;++$i)
    	echo str_repeat(" ", $len-$i),substr($str,-($i*2-1)),"\n";
}
echo pyramid("abracadabra");
?>
ぐはっ。9行目のechoは余計…。コピーしたのもろバレ。
ということでついでに別解。
空の文字列の並んだ配列をスペース挟んで繋ぐと
勝手にセンタリングされるという…。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php
function pyramid($str)
{
	$i=strlen($str);
	$a=array_fill( 0, $i, "");
	while(--$i>=0)
	{	$a[$i]=$str[$i];
		echo implode(" ",$a),"\n";
	}
}

pyramid("abracadabra");
?>

	
1
2
3
4
5
6
7
8
9
Sub pyramid(ByVal block As String)
    For i As Integer = 0 To block.Length - 1
        Dim line As String = Space(block.Length - i - 1)
        For j As Integer = 0 To i
            line &= " " & block.Substring(block.Length - i - 1 + j, 1)
        Next
        Console.WriteLine(line.Substring(1))
    Next
End Sub

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

void put_s(int n)
{
	int i;
	for (i = 0; i < n; i++) putchar(' ');
}

void put_c(const char *s)
{
	putchar(*s);
	
	while (*++s) {
		putchar(' ');
		putchar(*s);
	}
}
void pyramid(const char *s)
{
	int n;

	n = strlen(s);
	
	while (--n >= 0) {
		put_s(n);
		put_c(s + n);
		put_s(n);
		putchar('\n');
	}
}

int main()
{
	pyramid("hoge");
	pyramid("abracadabra");
	return 0;
}
REPLと二人三脚で作りました。
1
2
3
4
5
6
7
8
9
(defun pyramid (str)
  (let ((base (coerce (cdr (reduce (lambda (r x) `(,@r #\Space ,x))
				   (coerce str 'list)
				   :initial-value '())) 'string)))
    (do ((idx 2 (+ idx 2))
	 (len (length base))
	 (result base (concatenate 'string spacer (subseq base idx) "~%" result))
	 (spacer " " (concatenate 'string " " spacer)))
	((> idx len) (format t result)))))