#概要
Javaでアルファベット1種禁止(a~zのうち1種類を使わずに書く)でどのアルファベットが抜いても書けるかを検証した。ただの遊び。
#ルール
1.java10,Windows10
2.コンパイルはjavac, 実行はjavaでオプションなし(というかEclipseで書いて実行)
3. 標準出力にHello, world!と出力する
4. 余計な標準出力、エラー出力は禁止(改行はOK)
5.アルファベットを1種類だけ使用禁止
6.大文字小文字は区別なし
7.外部ファイル禁止(Java標準ライブラリのみ可能)
8.ユニコードエスケープ禁止(2018-08-26追記)※詳細は後述
#結論
可能:bfhjklpquwxyz
不可能:acdegimnorstv
#詳細
大体アルファベット順に縛ったコード書いてる。
##fjkqxz
普通に書いたHelloWorldに出てこない。ちなみに変数名、クラス名はアルファベット使わないように日本語にしてる。クラス名にアルファベット以外がつかえることを利用してる人っているのかな……。(教育用のソースコードに使われてたのを1回見た。)
class ハローワールド {
public static void main(String[] 引数) {
System.out.print("Hello, World!");
}
}
##b
interface内のメソッドはpublicが暗黙的に加わるのでmain文でも書く必要がなくなる。java7か8からの機能だった気がする。ただ結構ほかのところで使われてる文字が多いのでbしか対処できない。
interface ハローワールド {
static void main(String[] 引数) {
System.out.print("Hello, World!");
}
}
#hlpw
文字コードをフォーマット形式で入力してHello, worldにしか含まれてる文字列を使わないようにする。printfではなくformatにすることでpを使うことを回避し、interfaceにすることでpublicでplを使うことを回避してる。
interface ハローワールド {
static void main(String[] 引数) {
System.out.format("%c%c%c%c%c, %c%c%c%c%c!",72,101,108,108,111,87,111,114,108,100);
}
}
#uy
s[y]stem.o[u]tにはいっているのでどうにかしてこれを使わずに標準出力をする。
ScriptEngineというスクリプト言語を実行できるクラスがあって、スクリプトで出力を行うと標準出力される。
ただScriptEngineを取得するときにgetB[y]Nameメソッドを使うので、これをgetClass, getMethod,invokeを使い文字列から実行し、文字列ではyを数字から取得して解決する。
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
interface ハローワールド {
static void main(String[] 引数) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = (ScriptEngine)manager.getClass()
.getMethod("getEngineB"+(char)121+"Name", String.class).invoke(manager, "javascript");
String script = "print('Hello, World!')";
engine.eval(script);
}
}
#縛れない文字と理由
##acdgimnorstv
static void main(String[] 引数)が絶対必要なため、これに含まれているアルファベットは抜くことが出来ない。これがないとそもそも実行できない。これ対処する方法あるんだろうか。
(2018-08-26追記)JavaFXのApplicationを継承すればmain文を書かなくていいという情報を得た。
public class ハローワールド extends javafx.application.Application{
public void start(javafx.stage.Stage ステージ){
System.out.print("Hello, World!");
}
}
ただこれでもほとんどの文字が使われていてどの縛りも解決しなかった。mはSyste[m].out使わなければいけるんだけど、ScriptEngine[M]anagerは使えないし、[m]ethodとna[m]eが使えないのでリフレクションでごまかせない。
##e
uyと同じくSyst[e]m.outに入っているのでこれを使わずに出力できればいいのだが、Script[E]ngin[e]に入ってしまっているし、文字列から取得しようにもそもそもg[e]tClassに入ってる。というかg[e]tにはいっているので何かしらを取得するメソッドが使えない。そうでなくてもかなり使われやすいアルファベットなので引っかかりやすい。
#終わりに
以上より
可能:bfhjklpquwxyz
不可能:acdegimnorstv
となる。main文が邪魔すぎる。eはどうにかして解決する方法がありそうなんだけど……。
やりかたがあったら教えてください。
fizzbuzzあたりをやっても面白いかもしれない。
#(2018-08-26追記)ユニコードエスケープ禁止
コメントで情報を頂いた。Javaではユニコードエスケープ(\uxxxx)形式でソースコードを書ける。これを使えば理論上16進数のa~fとuを合わせたabcdefuしか出てこず、a~fはユニコードエスケープに変換してもそれぞれアルファベットを含まないので、各アルファベットのみをユニコードエスケープに変換すれば解決する。u以外はコードに関係なく縛ることが可能になる。それだとあんまり縛る意味が無い気がするので自分の縛りでは禁止とする。
こういう変なことしてると普通のプログラムでは使わないような情報が入ってきて面白い。