縛りプログラミング

こんにちは、LIFULL HOME'S事業本部 技術開発部の宮崎です。
これはLIFULL その2 Advent Calendarの8日目の投稿になります。
ついでにLIFULL Advent Calendarもよければご覧下さい。

縛りプログラミングとは

今回の記事は、僕がConfluenceの記事で出したある問題の解答集となります。
その問題が以下のとおりです。

ソースコードにダブルクォート、シングルクォート、数字を書くこと無く、「LIFULL」と出力して下さい。
最後に改行を付けること。
言語は問いません。

完全にHelloWorldですね。このHelloWorldを幾つかの縛りを設けて解いてみろ!という感じです。
この記事を見た方もどのような方法があるかぜひ考えてみて下さい。

幾つかは自分で実行の環境を用意するのがめんどくさかった用意できなかったので、動作確認できていないものがあります。

分類

どういう方法を用いたか大まかに分類してみることにします。
全ての解答は最後にまとめます。

異なるリテラルで文字列を表現

rubyの%qやヒアドキュメント、幾つかの言語では`を使うことで文字列を表現することができます。
また、PHPでは、PHPタグを使わないことで、直接文字列として認識させることもできるようです。

解答例
puts %q(LIFULL)

関数名やクラス名を文字列表現

スクリプト言語では、比較的簡単に関数名やクラス名を取得することができるので、その特徴を上手く活かしている解答です。

解答例
console.log((LIFULL = () =>{}).name)

実行時に頑張る

ソースコードにというのがレギュレーションなので、上手く穴を突いた解答です。

実行時の引数や、環境変数、ワンライナーでの解答がありました。

解答例
$ cat lifull.sh
#!/bin/bash
echo $VAR
$ VAR="LIFULL" ./lifull.sh

ASCIIコードで頑張る

そもそも文字はコンピューター内部では数字として保存されているようなものなので、数字を作ることができれば文字列を表示することができます。
問題はどうやって数字を作るかです。
解答の中では以下の様なものがありました。

  • 行番号を使う
  • 割り算する
  • 用意されている定数を使う
  • 言語特有のハックを使う(js,perl)
解答例
import java.awt.event.KeyEvent;

public class Lifull {
    public static void main(String[] args) {
        byte[] codes = new byte[]{KeyEvent.VK_L, KeyEvent.VK_I, KeyEvent.VK_F, KeyEvent.VK_U, KeyEvent.VK_L, KeyEvent.VK_L};
        System.out.printf(new String(codes) + System.lineSeparator());
    }
}

webページから文字列を取得する

LIFULLという文字が入っているページから文字列を取得し、頑張って数字を作れば文字列が抽出できます。

解答例
  1 <?php
  2 $url = <<<EOF
  3 http://toushi.homes.co.jp/
  4 EOF;
  5
  6 $num = __LINE__;

<>

480
481 $start = __LINE__;
482 $lifull = substr(file_get_contents($url),$start,$num);
483 print($lifull);
484 ?>
485

まとめ

今回この問題を作るにあたって僕が考えていた解答は ASCIIコードで頑張る でした。そこで数字を作る方法も割り算じゃなくて、ビット演算でした。しかも言語はCです。
その解答しか頭になかったのでいろんな言語で色んな方法を見て、言われてみれば当たり前だけど、頭が固くて気づいてなかったなぁと思いました。精進したい💪💪💪💪💪

それはそれとして、出した問題に対して反応が貰えるととても嬉しいです。仕事に関しても周りを巻き込めるようになると仕事ももっと面白くなるんだろうなぁと思います。

こういう解答もあるよ!!!!
という方はコメントをお願いします🙏🙏🙏

全回答

解答1

lifull.rb
puts %q(LIFULL)

解答2

lifull.py
class LIFULL: pass
print(LIFULL.__name__)

解答3

lifull.py
try:
    LIFULL
except NameError as e:
    a = str(e)

try:
    XXXXXX
except NameError as e:
    b = str(e)
print(str().join(x for x, y in zip(a, b) if x != y))

解答4

lifull.js
var s = `LIFULL\n`;
console.log(s);

解答5

lifull.php
<?php
echo <<<EOF
LIFULL\n
EOF;

解答6

lifull.php
LIFULL

解答7

lifull.php
<?php eval($argv[__LINE__]);
実行方法
php ans.php "echo \"LIFULL\n\";"

解答8

lifull.php
<?php




function LIFULL(){ error_log((__FUNCTION__), __LINE__);  }
LIFULL();

解答9

lifull.sh
#!/bin/bash
echo LIFULL

解答10

$ echo LIFULL

解答11

lifull.js
console.log(((![]+[])[+!![] + +!![]]+([][+!![]]+[])[+!![] + +!![] + +!![] + +!![] + +!![]]+([][+[]]+[])[+!![] + +!![] + +!![] + +!![]]+([][+[]]+[])[+[]]+(![]+[])[+!![] + +!![]]+(![]+[])[+!![] + +!![]]).toUpperCase());

解答12

lifull.js
console.log((LIFULL = () =>{}).name)

解答13

lifull.R
v <- deparse(quote(`LIFULL\n`))
cat(v)

動作未確認

解答14

lifull.R
one <- pi/pi
two <- floor(pi) - one
three <- ceiling(pi) - one

six <- two * three
seven <- six + one
nine <- three * three
twelve <- three * two * two
twentyone <- three * seven

newline <- deparse(quote(`\n`))

v <- c(LETTERS[c(twelve,nine,six,twentyone,twelve,twelve)], newline)

s <- character(one)

cat(v, sep=s)

動作未確認

解答15

lifull.php
  1 <?php
  2 $url = <<<EOF
  3 http://toushi.homes.co.jp/
  4 EOF;
  5
  6 $num = __LINE__;

<>

480
481 $start = __LINE__;
482 $lifull = substr(file_get_contents($url),$start,$num);
483 print($lifull);
484 ?>
485

解答16

lifull.js
console.log(/LIFULL/.source);

解答17

lifull_spec.rb
class LIFULL
end

describe LIFULL do
  it do
    puts described_class
  end
end
実行方法
$ rspec lifull_spec.rb

他の文字列が含まれているためレギュレーション的にはグレー

解答18

lifull.sh
#!/bin/bash
echo $VAR
実行方法
$ VAR="LIFULL" ./lifull.sh

解答19

public enum COMPANY { LIFULL }
system.debug(COMPANY.LIFULL);

動作未確認

解答20

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
---.
---.
+++++++++++++++.
---------.
.
------------------------------------------------------------------.

解答21

lifull.lisp
(print (concatenate (quote string) (list #\L #\I #\F #\U #\L #\L #\linefeed)))

動作未確認

解答22

perl6 -e '::((~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~^q{:}~^q{(}~q{)}~^q{(}~^q{~}~^q{:}~q{~}~^q{(}~q{)}~^(~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~^(~(^(q{}~~q{})))~^q{~}~^q{:}~^q{(}~q{^}~^q{(}~^q{:})(q{(}~^(~(^(q{}~~q{})))~^q{:}~q{^}~^(~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~^(~(^(q{}~~q{})))~^q{)}~q{:}~^q{)}~^q{(}~^q{^}~^(~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~^(~(^(q{}~~q{})))~q{:}~^q{)}~^(~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~^q{^}~q{~}~^q{^}~q{:}~^(~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~^q{)}~q{^}~^q{(}~^q{:}~q{)}~^(~(^(q{}~~q{})))~^q{:}~^(~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~^q{^}~(~(^(q{}~~q{})))~^q{^}~^q{(}~(~(^(q{}~~q{})))~^q{(}~^q{)}~^q{:}~^q{^}~q{^}~^q{(}~^q{:}~q{^}~^q{(}~^q{:}~q{:}~^(~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~^q{)}~q{(}~^(~(^(q{}~~q{})))~^q{:}~q{^}~^q{:}~^q{~}~^(~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~q{)}~^q{(}~^q{~}~^q{:}~q{~}~^q{(}~q{)}~^(~::((~(^(q{}~~q{})))~^q{~}~q{)}~^q{(}~^q{:}~^(~(^(q{}~~q{})))~^q{~}~q{)}~^q{~}~^q{:})((~(^(q{}~~q{})))~^q{)}~^q{(}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{~}~^q{^}~^(~(^(q{}~~q{})))~^q{:}~q{:}~^q{~}~^q{(}~^q{^}))~^(~(^(q{}~~q{})))~^q{~}~^q{:}~^q{(}~q{^}~^q{(}~^q{:})'

動作未確認

解答23

lifull.pl
print <<EOF;
LIFULL
EOF

解答24

lifull.sql
SELECT
    CHR(eight * nine + four) AS l, -- 76
    CHR(eight * nine + one) AS i, -- 73
    CHR(eight * nine - two) AS f, -- 70
    CHR(nine * nine + four) AS u, -- 85
    CHR(eight * nine + four) AS l, -- 76
    CHR(eight * nine + four) AS l, -- 76
    CHR(nine + one) AS lf --10
FROM (
    SELECT
        one,
        one + one AS two,
        one + one + one AS three,
        one + one + one + one AS four,
        one + one + one + one + one AS five,
        one + one + one + one + one + one AS six,
        one + one + one + one + one + one + one AS seven,
        one + one + one + one + one + one + one + one AS eight,
        one + one + one + one + one + one + one + one + one AS nine
    FROM (
        SELECT DISTINCT
        (SELECT COUNT(*)/COUNT(*) FROM hoge) AS one
        FROM hoge
    ))

動作未確認

解答25

tcl
puts {LIFULL}

動作未確認

解答26

Lifull.java
import java.awt.event.KeyEvent;

public class Lifull {
    public static void main(String[] args) {
        byte[] codes = new byte[]{KeyEvent.VK_L, KeyEvent.VK_I, KeyEvent.VK_F, KeyEvent.VK_U, KeyEvent.VK_L, KeyEvent.VK_L};
        System.out.printf(new String(codes) + System.lineSeparator());
    }
}

解答27

lifull.hs
data Company = LIFULL | RECRUIT | ATHOME deriving Show

main :: IO ()
main = print LIFULL

解答28

sqlplus
PROMPT LIFULL

動作未確認

解答29

whitespace
SSSSN
SSSTSTSN
SSSTSSTTSSN
SSSTSSTTSSN
SSSTSTSTSTN
SSSTSSSTTSN
SSSTSSTSSTN
SSSTSSTTSSN
N
SSSSN
SN
SN
TSSTN
TN
SSN
SN
SSN
N
SSSTN
N
N
N
N

動作未確認

※以下追記

解答30

lifull.pl
s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s qq q and s s s chr length q qr open bind when wait for untie exp q semop and s s s chr length q q chomp local tie alarm write undef tied tied goto warn xor tie for chown warn rmdir fork chomp q semop and s s s chr length q qr open die for recv atan read pack ord chdir order print map q semop and s s s chr length q qr fcntl print int link utime pack q semop and s s s chr length q qr fcntl print int link utime pack q semop and s s s chr length q q chomp local tie alarm write undef tied tied goto warn xor q semop and s s s chr length q q chomp local tie alarm write undef tied tied goto warn xor tie for chown warn rmdir not fcntl grep glob getc pack eof q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor tie for chown warn rmdir fork chomp chown rmdir each q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor tie for chown warn rmdir not fcntl grep glob getc pack q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor tie for chown warn rmdir not fcntl grep chown q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q qr open die for recv atan read pack ord getc rand dump log xor our read map map kill exp crypt each lock print q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor tie for chown warn rmdir not fcntl grep chown lock chown q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q qr open bind when wait for untie q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q qr fcntl print int link utime pack q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor tie for cmp pack q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor tie for chown q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor kill chmod q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor kill chmod map while exec q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor tie for cmp pack q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q q chomp local tie alarm write undef tied tied goto warn xor tie for cmp pack q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q qr open die for recv atan read pack ord getc rand dump log xor our read atan eval undef recv q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q qr open die for recv atan read pack ord getc rand dump log xor our read map map kill exp crypt each lock print q semop and s s s chr length q qr open die for recv atan read pack chop break q semop and s s s length q qr fcntl print int link utime pack q semop and eval eval
33contribution

JavaとKotlinで書いてみました!

lifull.java
public class LIFULL {
    public static void main(String[] args){
        System.out.println(LIFULL.class.getSimpleName());
    }
}
lifull.kt
fun main(args: Array<String>) {
    println(LIFULL::class.java.simpleName)
}

object LIFULL

javaは未検証ですがkotlinは動作しました。

114contribution
lifull.c
#include<stdio.h>
#define tostr(s) #s
int main(void){puts(tostr(LIFULL));}
48contribution

@C6H2Cl2 syntax errorかと思われます…

33contribution

@imishinist おうふ…
println()の)忘れてましたね…
修正しておきました
ありがとうございます