「不正行為」;-) しかし、非常に短い解決策は
#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ます。1234
この の一連の値についてi、式が, , , , , , , , , ...とi < 6 ? i : 11 - i評価されることは簡単にわかります (これはDrew Dorman のソリューションに従って表現することもできますが、三項演算子を使用すると必要がなくなります行を保存する ;-) これらの数値は、毎回表示される "INDIA" の文字数です。123455432105.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の受賞者を参照してください。楽しみ!