challenge Hello, world!その2

「Hello, world!」と表示するプログラムを作ってください。 ただし、コード中に同じアルファベットが2回出現してはいけません。

アルファベットとは、小文字のa-zと大文字のA-Zを指すものとします。また、大文字と小文字は区別するものとします。つまり、記号や空白文字は何度出現しても構いませんし、小文字のgと大文字のGの両方を使うのは構いません。

単純な「print "Hello, world!"」はrとoとlが2回以上使われているので題意を満たしません。

この問題はHello, world!の上級編です。

HSP では文字列以外の大文字小文字の区別がないので、区別しないでやってみました。”いかれ具合”は高いと思います。小さなウィンドウが 34 個出ますので、実行するときは気をつけてください。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
_0(   0 ) =  31,  13,  11,  73,  38,  44,  48,   8,  78,  16,  11,  69
_0(  12 ) = 111,  51,  37,   9, 138,  35,  10,  22, 112,  28,  32,  11
_0(  24 ) = 108,  33,  10,  46, 110,  74,  30,  10, 161,  10,   9,  74
_0(  36 ) = 193,   9,   9,  72, 228,  32,  27,   9, 249,  37,  12,  39
_0(  48 ) = 225,  76,  31,  10, 221,  36,  10,  44, 273,  77,  15,  11
_0(  60 ) = 280,  84,   7,  14, 335,  44,   9,  40, 359,  33,  12,  51
_0(  72 ) = 338,  80,  53,   9, 383,  47,  14,  45, 412,  36,  31,   8
_0(  84 ) = 438,  39,   9,  43, 412,  78,  29,   7, 405,  41,  12,  40
_0(  96 ) = 461,  34,   9,  53, 464,  44,  29,  10, 503,  10,   8,  73
_0( 108 ) = 564,  10,  10,  78, 540,  40,  28,   9, 532,  45,  11,  39
_0( 120 ) = 536,  76,  32,  10, 592,  13,  12,  52, 591,  75,  14,  12

_1 = 0
do
    bgscr _1 + 1, _0( _1 + 2 ), _0( _1 + 3 ), 0, _0( _1 + 0 ), _0( _1 + 1 )
    _1 += 4
until _1 > 128

Posted feedbacks - Flatten

Nested Hidden
brainf*ck
1
 ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

print packだとpの文字が2回出現してしまうので使えない...
1
die pack "C*", qw(72 101 108 108 111 44 32 119 111 114 108 100 33 10);

unpack version
1
die unpack "\165","/2&5L;&\\\Ul('=o<FQD(0T*"

素直にPerlで、同じ数字も出てこない
1
print "Hel\154o, w\LOR\x6cd!";

数字はいいんですよね?
1
2
3
main(){
	puts("He\154\154\157,World!");
}

Common Lispでは大文字と小文字は文字列以外では区別されない。その性質を使って作った。
1
2
(DOlist (j '(72 101 108 108 111 32 119 111 114 108 100 33))
	   (PRINC (Code-char J)))

一応動いた感
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?
$_1[] = '72';
$_1[] = '101';
$_1[] = '108';
$_1[] = '108';
$_1[] = '111';
$_1[] = '44';
$_1[] = '32';
$_1[] = '119';
$_1[] = '111';
$_1[] = '114';
$_1[] = '108';
$_1[] = '100';
$_1[] = '33';
for($_2 = 0; $_2 < 13; $_2++) {
  echO CHR($_1[$_2]);
}
?>

インスパイアされてPerl版です。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
die map { chr }  (
        72,
        101,
        108,
        108,
        111,
        44,
        32,
        119,
        111,
        114,
        108,
        100,
        33,
);

Cがかぶってるように見えます。 かといって、解決案もないんですが。

awk でも 8 進数が扱えます。
1
BEGIN{print "\110\145\154\154\157\054\040\167\157\162\154\144\041"}

24字。Perl だとこれが限界?
1
print+H,lc"eLLo, wORLd!"

がーん。題意が違った orz
1
$_="He00o, w360d!";y/0-7/l-s/;print

8進数を使ったものです.
1
ruby -e 'puts "\110\145\154\154\157\54\40\167\157\162\154\144\41"'

HQ9+
1
H

結構悩んだ。
1
"Helo,Wrd!".gsub(/(.{2})(.)(.)(.{2})(.)(.{2})/) {$1+$2+$2+$3+$4+$3+$5+$2+$6}

文字の重複いっさいなしで
1
print+q[)./*%h>-7ld!]^aKCFJHIBE

Javaだとclassだけで文字の重複があるので実現不可能だと思います(残念)

1
2
3
: e
s${_}t r l o $_
$4ch$3 H$4$2$2$3, W$3$1$2d!

あ、unicodeエスケープ使えばいいのか。でもuが重なるから1回しか使えない。publicにuが入っているし。やはり無理か……

あ、^^; ほんとだ。解決策は思い浮かばないんだよなぁ。

被ってる文字にラベルを付けてみました
1
2
(maP () 'princ
     '(#\H #\e #1=#\l #1# #2=#\o #\  #\W #2# #\r #1# #\d #\!))

CLISP 限定ですが。
1
2
(DOSEQ (j '(72 101 108 108 111 32 119 111 114 108 100 33))
       (PRINC (int-char J)))

Pythonがなかったので一応。
1
print "Hel\154o, W\157\162\154d!"

我ながらいけてない>< JavaScript でこれは難しかった。
1
_='\\u00';$='rtcf';eval(_+61+_+'6'+$[2]+_+65+$[0]+$[1]+'("'+_+48+_+65+_+'6'+$[2]+_+'6'+$[2]+_+'6'+$[3]+', '+_+77+_+6+$[3]+$[0]+_+'6'+$[2]+_+64+'!")');

おなじく JavaScript
1
2
_=['e','a','\x72','o','C'];
[][_[0]+'v'+_[1]+'l'](String['f'+_[2]+_[3]+'m'+_[4]+'h'+_[1]+_[2]+_[4]+_[3]+'d'+_[0]](97,108,101,114,116,40,34,72,101,108,108,111,44,32,87,111,114,108,100,33,34,41))

eval 使わない版
1
2
3
$=this;
_=['a','e','r','\x74','\u0069','o','C'];
$[_[0]+'l'+_[1]+_[2]+_[3]]($['S'+_[3]+_[2]+_[4]+'ng']['f'+_[2]+_[5]+'m'+_[6]+'h'+_[0]+_[2]+_[6]+_[5]+'d'+_[1]](72,101,108,108,111,44,32,87,111,114,108,100,33))

1
2
3
4
5
<?php
for($i=1,$sa=array(72,29,7,0,3,-67,-12,87,-8,3,-6,-8,-67,0);$i<count($sa);$sa[0] += $sa[$i++]){
 echo chr($sa[0]);
}
?>

フォロー。ありがとうございます。


	
1
(string 72 101 108 108 111 44 32 119 111 114 108 100 33)

$&と$'をつかうことでで記号だけで参照
1
"lo"=~/./;puts"He#{$&*2+$'}, w#$'r#$&d!"

何故こうしないのかが不思議です。
1
2
3
main(){
    puts("\110\145\154\154\157\54\127\157\162\154\144\41");
}

目指せ最短。『表示する』の意味に少し迷った。
1
alert(['\110\145\154\154\157\54\40\167\157\162\154\144\41']);

何故と聞かれれば文字減らすためとしか。

こうしたほうがさらに短くなるのではないでしょうか
1
alert('H\145\154\154o, w\157\162\154d!');

C#では正攻法ではできない気がする。 Debug.Printでusing System.Diagnosticsは見逃してもらう方向で考えたけど、\nnnの8進数リテラルが限定的にしか使えないので無理っぽい。 .NETは基本的にメソッド名とかが明示的で長くて省略形も無いのでこういう課題は苦しいっす。

c++だとこんな感じでしょうか
1
2
3
main(){
    cout << "He\154\154\157, W\157rld!";
}

data スキームを使っているので、 IE では動きません。 e がちょっと不恰好かも。 ところで皆さんは、文字列をどのようにして 8進数に変換しているのでしょうか?
1
eval('\144\157\143\165\155\145\156\164\56\167\162\151\164\145\50\47\74\151\155\147\40\163\162\143\75\144\141\164\141\72\151\155\141\147\145\57\147\151\146\73\142\141\163\145\66\64\54\122\60\154\107\117\104\154\150\112\167\101\106\101\111\101\101\101\120\57\57\57\167\101\101\101\103\167\101\101\101\101\101\112\167\101\106\101\101\101\103\111\167\167\143\145\121\166\164\104\66\106\160\103\103\60\67\157\64\66\65\161\157\121\144\103\165\126\64\61\57\127\106\160\110\161\107\157\64\160\71\161\110\127\113\71\110\167\125\101\104\163\75\76\47\51\73');

Squeak Smalltalk ではこれが精一杯。w
1
2
3
'', 2645608968347327576478451524936

"=> 'Hello, world!' "

よく考えたらpackがあったなぁ
1
2
3
<?
die(pack('C*', 72,101,108,108,111,32,119,111,114,108,100,33));
?>

中味が「class a{static void Main(){System.Console.WriteLine("Hello, world!");}}」のファイルaを用意して置く。 ううむ、無理やりすぎる。
1
csC a|A

1
io:put_chars([72,101,108,108,111,44,32,119,111,114,108,100,33,10]).

aが7回
cが3回
hが3回
iが2回
oが3回
pが2回
rが4回
sが5回つかわれているので失格

#↑を表示するプログラムを作れ,ってお題はどうだろう。

じゃ、早速
でも、絶対こういうのはperlとかの方が得意に決まってる。

(define h (make-hash-table 'eqv?))

(let loop ((c (read-char)))
  (unless (eof-object? c)
    (when (char-set-contains? #[a-zA-Z] c) (hash-table-update! h c (pa$ + 1) 0))
    (loop (read-char))))

(define f #f)

(hash-table-for-each h
  (lambda (key val)
    (when (> val 1)
      (set! f #t)
      (print #`",|key|が,|val|回"))))

(print
  (if f
    "使われているので失格"
    "重複した文字は有りません!"))

rもかぶってますね。pRincにすればOKかな。

これは…文字列連結によって数値が文字列にcoerceされるんですね。2645... を16進で見てみると右から左へ H e l l o ... と詰まっているみたいですが、それはそういうものなんですか?

おっと、この余分な投稿で、HelloWorld!その2をschemeで解いたことになっちゃってますね。すみません、削除してもらえますか?あるいは、言語をschemeからOthersにしてもらうか。>>管理者様

1
printf "\072\101\108\108\111\044\032\119\111\114\108\100\033\010";;

以下のようなことで参考になりますかどうか…。

'abcd' size        "=> 4 "
'abcd' byteAt: 1   "=> 97 "
'abcd' asByteArray   "=> a ByteArray(97 98 99 100) "

1684234849 size    "=> 4 "
1684234849 at: 1   "=> 97 "
1684234849 as: ByteArray   "=> a ByteArray(97 98 99 100) "

'', 'abcd'       "=> 'abcd' "
'', 1684234849   "=> 'abcd' "
'', #(97 98 99 100) asByteArray   "=> 'abcd' "

JAPH的なコードが増えれば面白いですね (自分のは全く面白くないコードですが)
1
cat("Hel\154o, w\157r\154d!")

いちおう。
1
println("He\154\154\157,World!");

VMで動いてるんですよね? 実CPUのエンディアンに関わらず、整数はlittle endianの可変長オクテット列って扱いと理解すれば良いでしょうか。可変長にするならlittle endianは妥当な選択だと思います。 それにしても、意外なところでバイナリアンっぽくて(rawな表現を見せていて)新鮮でした。

同じ発想をGaucheで。

他の手はないかどうか色々考えてみたのだけれど、
- 文字列内エスケープは \x とか \u などアルファベットが入ってしまうので1回づつしか使えない
- バイナリ操作やI/Oを行う手続きやモジュールは既にそれだけで重複文字を含んでいる

などなど、意外に難しい。しかもデフォルトでcase sensitiveだからCommon Lispみたいに
caseを変える回避法も使えないし。
1
(print #\H #\e #1=#\l #1# #2=#\o #\, #\  #\W #2# #\u0072 #1# #\d #\!)

整数でも無限倍精度整数でなくては駄目みたいです。

'', ('abc' as: LargePositiveInteger)   "=> 'abc' "
'', 16r636261   "=> Error: Instances of SmallInteger are not indexable "
'', 16r64636261   "=> 'abcd' "

いまごろなでしこで、
1
2
3
甲は「l」
乙は「o」
「He{甲}{甲}{乙}, w{乙}r{甲}d!」を表示。

日本語プログラミング言語で解決とは、意表をつかれました。Mind言語でもできますかね?その他ヨーロッパ系の言語とかあったりして。。。