「不正行為」;-) しかし、非常に短い解決策は
#include <cstdio>
int main() {
puts("I\nIN\nIND\nINDI\nINDIA\nINDIA\nINDI\nIND\nIN\nI\n");
}
TonyKの美しいアイデアに基づくさらに別のソリューション(C および C++ で動作):
#include <stdio.h>
int main() {
for (int i = 1; i < 11; ++i)
printf("%.*s\n", i < 6 ? i : 11 - i, "INDIA") ;
}
更新:(TonyKのコメントの後):
スペースが必要な場合は、printf
上記をこれに置き換えます
printf("%.*s\n", 2*(i < 6 ? i : 11 - i), "I N D I A ");
更新:ループのないソリューション:
#include <stdio.h>
int main(int i, char**) {
return printf("%.*s\n", i < 6 ? i : 11 - i, "INDIA") - 1 && main(i + 1, 0);
}
初心者向けの詳細な説明が続きます。
最も重要な点は、これが「アカデミック」な演習であるということです。コードはわかりにくく、このような深刻なコードを書くことは控えるべきです。
標準は、関数の特定の署名を修正しませんmain
。int
を返す必要があり、コンパイラは 2 つの特定の形式を受け入れる必要があることのみを示しています。
int main();
int main(int argc, char** argv);
私は2番目のものを使用しています。より一般的な形式int main(int argc, char* argv[])
は (2) と同等です。実際、一般に、関数の引数として使用されるT の配列は、暗黙的に T へのポインターに変換されます。この例では、 は char へのポインタへのポインタになるchar へchar* argv[]
のポインタの配列です。ただし、上記のプログラムは 2 番目のパラメーターを使用していません (無視されるか、NULL、つまり値 0 が指定されます)。
ループを実行する代わりに、プログラムはmain
再帰的に呼び出します。実際、これは違法ですが、主要なコンパイラはこれに目をつぶっています (オプション -Wpedantic でペダンティックにするように要求した場合、GCC はせいぜい警告を出します)。引数なしでコマンドラインからプログラムが呼び出されると、オペレーティングシステムは、main
引き渡し1
( 1
+ 引数の数) と、前述のように、このプログラムによって無視されるchar へのポインターへのポインターを呼び出します。したがって、i = 1
最初の呼び出しで。
その後、main
潜在的に自分自身をi
毎回インクリメントして呼び出します。要約すると、、 、、、 ...main
と順次呼び出されi
ます。1
2
3
4
この の一連の値についてi
、式が, , , , , , , , , ...とi < 6 ? i : 11 - i
評価されることは簡単にわかります (これはDrew Dorman のソリューションに従って表現することもできますが、三項演算子を使用すると必要がなくなります行を保存する ;-) これらの数値は、毎回表示される "INDIA" の文字数です。1
2
3
4
5
5
4
3
2
1
0
5.5 - abs(5.5 - i)
#include <cmath>
呼び出しprintf("%.s\n", j, "INDIA")
は、 "INDIA"j = i < 6 ? i : 11 - i
の最初のj
文字とそれに続く改行を表示し、(改行を含めて) 有効に印刷された文字数、つまり を返しますj + 1
。1
利回りを奪うj
。
a && b
ここで、整数a
およびに対するのセマンティクスの重要な点を思い出してb
ください。a == 0
の場合b
は評価されません。それ以外の場合b
は評価されます。私たちにとって、a = printf("%.*s\n", j, "INDIA") - 1
(つまりa = j
) とb = main(i + 1, 0)
.
では、これらのパーツを組み合わせてみましょう。
1.最初に、i = 1
およびj = 1
. への呼び出しはprintf
"I\n" を出力し、 を返します2
。奪う1
、与えるa = 1 != 0
。したがって、b = main(2, 0)
が評価されます (つまり、main(2, 0)
呼び出されます)。
2.この 2 回目の呼び出しmain
ではi = 2
、がありj = 2
、printf
"IN\n" が表示され、a = 2 != 0
評価b = main(3, 0)
されます。
を呼び出すたびに、この引数を繰り返すと、次のようになりmain
ます。
3. i = 3
, j = 3
, "IND\n" が出力され、a = 3 != 0
呼び出さmain(4, 0)
れます。
4. i = 4
, j = 4
, "INDI\n" が出力され、a = 4 != 0
呼び出さmain(5, 0)
れます。
5. i = 5
, j = 5
, "INDIA\n" と出力され、a = 5 != 0
呼び出さmain(6, 0)
れます。
6. i = 6
, j = 5
, "INDIA\n" と出力され、a = 5 != 0
呼び出さmain(7, 0)
れます。
7. i = 7
, j = 4
, "INDI\n" が出力され、a = 4 != 0
呼び出さmain(8, 0)
れます。
...
10. i = 10
, j = 1
, "I\n" が出力され、a = 1 != 0
呼び出さmain(11, 0)
れます。
11. i = 11
、j = 0
、「\n」が印刷されa = 0
ます。現在main(12, 0)
は実行されておらず、main
返品
main
ステップ 1main
ではステップ 2 が呼び出さmain
れ、ステップ 113
では ... が呼び出されることに注意してくださいmain
。したがって、main
ステップ 11 では に戻りmain
、ステップ 10 では に戻りmain
、ステップ 9 では ... に戻りますmain
。ステップ 1. 最後にmain
、ステップ 1 でオペレーティング システムに戻ります。
さらに難読化されたコードに興味がある場合は、現在および過去のIOCCCの受賞者を参照してください。楽しみ!