Задача: печать чисел от 1 до 1000 без использования каких-либо циклов или условных операторов. Не просто пишите инструкцию printf()
или cout
1000 раз.
Как вы это сделаете с помощью C или С++?
Рекурсия времени компиляции!: P
#include <iostream>
template<int N>
struct NumberGeneration{
static void out(std::ostream& os)
{
NumberGeneration<N-1>::out(os);
os << N << std::endl;
}
};
template<>
struct NumberGeneration<1>{
static void out(std::ostream& os)
{
os << 1 << std::endl;
}
};
int main(){
NumberGeneration<1000>::out(std::cout);
}
Этот фактически компилируется в сборку, которая не имеет никаких условных выражений:
#include <stdio.h>
#include <stdlib.h>
void main(int j) {
printf("%d\n", j);
(&main + (&exit - &main)*(j/1000))(j+1);
}
Эта версия выше в стандарте C, так как она не полагается на арифметику на указатели функций:
#include <stdio.h>
#include <stdlib.h>
void f(int j)
{
static void (*const ft[2])(int) = { f, exit };
printf("%d\n", j);
ft[j/1000](j + 1);
}
int main(int argc, char *argv[])
{
f(1);
}
#include <stdio.h>
int i = 0;
p() { printf("%d\n", ++i); }
a() { p();p();p();p();p(); }
b() { a();a();a();a();a(); }
c() { b();b();b();b();b(); }
main() { c();c();c();c();c();c();c();c(); return 0; }
Я удивлен, что никто, кажется, не опубликовал это - я думал, что это самый очевидный способ. 1000 = 5*5*5*8.
Похоже, что не нужно использовать циклы
printf("1 10 11 100 101 110 111 1000\n");
copy
- это обман
printf
есть цикл: p
Вот три решения, которые я знаю. Во-вторых, можно утверждать, что.
// compile time recursion
template<int N> void f1()
{
f1<N-1>();
cout << N << '\n';
}
template<> void f1<1>()
{
cout << 1 << '\n';
}
// short circuiting (not a conditional statement)
void f2(int N)
{
N && (f2(N-1), cout << N << '\n');
}
// constructors!
struct A {
A() {
static int N = 1;
cout << N++ << '\n';
}
};
int main()
{
f1<1000>();
f2(1000);
delete[] new A[1000]; // (3)
A data[1000]; // (4) added by Martin York
}
[Изменить: (1) и (4) можно использовать только для констант времени компиляции, (2) и (3) можно использовать для выражений времени выполнения too — редактирование. ]
Я не пишу инструкцию printf 1000 раз!
printf("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59\n60\n61\n62\n63\n64\n65\n66\n67\n68\n69\n70\n71\n72\n73\n74\n75\n76\n77\n78\n79\n80\n81\n82\n83\n84\n85\n86\n87\n88\n89\n90\n91\n92\n93\n94\n95\n96\n97\n98\n99\n100\n101\n102\n103\n104\n105\n106\n107\n108\n109\n110\n111\n112\n113\n114\n115\n116\n117\n118\n119\n120\n121\n122\n123\n124\n125\n126\n127\n128\n129\n130\n131\n132\n133\n134\n135\n136\n137\n138\n139\n140\n141\n142\n143\n144\n145\n146\n147\n148\n149\n150\n151\n152\n153\n154\n155\n156\n157\n158\n159\n160\n161\n162\n163\n164\n165\n166\n167\n168\n169\n170\n171\n172\n173\n174\n175\n176\n177\n178\n179\n180\n181\n182\n183\n184\n185\n186\n187\n188\n189\n190\n191\n192\n193\n194\n195\n196\n197\n198\n199\n200\n201\n202\n203\n204\n205\n206\n207\n208\n209\n210\n211\n212\n213\n214\n215\n216\n217\n218\n219\n220\n221\n222\n223\n224\n225\n226\n227\n228\n229\n230\n231\n232\n233\n234\n235\n236\n237\n238\n239\n240\n241\n242\n243\n244\n245\n246\n247\n248\n249\n250\n251\n252\n253\n254\n255\n256\n257\n258\n259\n260\n261\n262\n263\n264\n265\n266\n267\n268\n269\n270\n271\n272\n273\n274\n275\n276\n277\n278\n279\n280\n281\n282\n283\n284\n285\n286\n287\n288\n289\n290\n291\n292\n293\n294\n295\n296\n297\n298\n299\n300\n301\n302\n303\n304\n305\n306\n307\n308\n309\n310\n311\n312\n313\n314\n315\n316\n317\n318\n319\n320\n321\n322\n323\n324\n325\n326\n327\n328\n329\n330\n331\n332\n333\n334\n335\n336\n337\n338\n339\n340\n341\n342\n343\n344\n345\n346\n347\n348\n349\n350\n351\n352\n353\n354\n355\n356\n357\n358\n359\n360\n361\n362\n363\n364\n365\n366\n367\n368\n369\n370\n371\n372\n373\n374\n375\n376\n377\n378\n379\n380\n381\n382\n383\n384\n385\n386\n387\n388\n389\n390\n391\n392\n393\n394\n395\n396\n397\n398\n399\n400\n401\n402\n403\n404\n405\n406\n407\n408\n409\n410\n411\n412\n413\n414\n415\n416\n417\n418\n419\n420\n421\n422\n423\n424\n425\n426\n427\n428\n429\n430\n431\n432\n433\n434\n435\n436\n437\n438\n439\n440\n441\n442\n443\n444\n445\n446\n447\n448\n449\n450\n451\n452\n453\n454\n455\n456\n457\n458\n459\n460\n461\n462\n463\n464\n465\n466\n467\n468\n469\n470\n471\n472\n473\n474\n475\n476\n477\n478\n479\n480\n481\n482\n483\n484\n485\n486\n487\n488\n489\n490\n491\n492\n493\n494\n495\n496\n497\n498\n499\n500\n501\n502\n503\n504\n505\n506\n507\n508\n509\n510\n511\n512\n513\n514\n515\n516\n517\n518\n519\n520\n521\n522\n523\n524\n525\n526\n527\n528\n529\n530\n531\n532\n533\n534\n535\n536\n537\n538\n539\n540\n541\n542\n543\n544\n545\n546\n547\n548\n549\n550\n551\n552\n553\n554\n555\n556\n557\n558\n559\n560\n561\n562\n563\n564\n565\n566\n567\n568\n569\n570\n571\n572\n573\n574\n575\n576\n577\n578\n579\n580\n581\n582\n583\n584\n585\n586\n587\n588\n589\n590\n591\n592\n593\n594\n595\n596\n597\n598\n599\n600\n601\n602\n603\n604\n605\n606\n607\n608\n609\n610\n611\n612\n613\n614\n615\n616\n617\n618\n619\n620\n621\n622\n623\n624\n625\n626\n627\n628\n629\n630\n631\n632\n633\n634\n635\n636\n637\n638\n639\n640\n641\n642\n643\n644\n645\n646\n647\n648\n649\n650\n651\n652\n653\n654\n655\n656\n657\n658\n659\n660\n661\n662\n663\n664\n665\n666\n667\n668\n669\n670\n671\n672\n673\n674\n675\n676\n677\n678\n679\n680\n681\n682\n683\n684\n685\n686\n687\n688\n689\n690\n691\n692\n693\n694\n695\n696\n697\n698\n699\n700\n701\n702\n703\n704\n705\n706\n707\n708\n709\n710\n711\n712\n713\n714\n715\n716\n717\n718\n719\n720\n721\n722\n723\n724\n725\n726\n727\n728\n729\n730\n731\n732\n733\n734\n735\n736\n737\n738\n739\n740\n741\n742\n743\n744\n745\n746\n747\n748\n749\n750\n751\n752\n753\n754\n755\n756\n757\n758\n759\n760\n761\n762\n763\n764\n765\n766\n767\n768\n769\n770\n771\n772\n773\n774\n775\n776\n777\n778\n779\n780\n781\n782\n783\n784\n785\n786\n787\n788\n789\n790\n791\n792\n793\n794\n795\n796\n797\n798\n799\n800\n801\n802\n803\n804\n805\n806\n807\n808\n809\n810\n811\n812\n813\n814\n815\n816\n817\n818\n819\n820\n821\n822\n823\n824\n825\n826\n827\n828\n829\n830\n831\n832\n833\n834\n835\n836\n837\n838\n839\n840\n841\n842\n843\n844\n845\n846\n847\n848\n849\n850\n851\n852\n853\n854\n855\n856\n857\n858\n859\n860\n861\n862\n863\n864\n865\n866\n867\n868\n869\n870\n871\n872\n873\n874\n875\n876\n877\n878\n879\n880\n881\n882\n883\n884\n885\n886\n887\n888\n889\n890\n891\n892\n893\n894\n895\n896\n897\n898\n899\n900\n901\n902\n903\n904\n905\n906\n907\n908\n909\n910\n911\n912\n913\n914\n915\n916\n917\n918\n919\n920\n921\n922\n923\n924\n925\n926\n927\n928\n929\n930\n931\n932\n933\n934\n935\n936\n937\n938\n939\n940\n941\n942\n943\n944\n945\n946\n947\n948\n949\n950\n951\n952\n953\n954\n955\n956\n957\n958\n959\n960\n961\n962\n963\n964\n965\n966\n967\n968\n969\n970\n971\n972\n973\n974\n975\n976\n977\n978\n979\n980\n981\n982\n983\n984\n985\n986\n987\n988\n989\n990\n991\n992\n993\n994\n995\n996\n997\n998\n999\n1000\n");
Добро пожаловать;)
printf("%d\n", 2);
printf("%d\n", 3);
Он не печатает все числа, но он "печатает номера от 1 до 1000". Неоднозначный вопрос для победы!:)
Использование системных команд:
system("/usr/bin/seq 1000");
/usr/bin/seq
использует цикл внутри. :)
Запустить фатальную ошибку! Здесь файл, countup.c:
#include <stdio.h>
#define MAX 1000
int boom;
int foo(n) {
boom = 1 / (MAX-n+1);
printf("%d\n", n);
foo(n+1);
}
int main() {
foo(1);
}
Скомпилируйте, затем выполните в командной строке:
$ ./countup
1
2
3
...
996
997
998
999
1000
Floating point exception
$
Это действительно печатает числа от 1 до 1000 без каких-либо циклов или условных обозначений!
\n
будет достаточно для сброса вывода.
Немного скучно по сравнению с другими здесь, но, вероятно, то, что они ищут.
#include <stdio.h>
int f(int val) {
--val && f(val);
return printf( "%d\n", val+1);
}
void main(void) {
f(1000);
}
Неподтвержденный, но должен быть ванильным стандартом C:
void yesprint(int i);
void noprint(int i);
typedef void(*fnPtr)(int);
fnPtr dispatch[] = { noprint, yesprint };
void yesprint(int i) {
printf("%d\n", i);
dispatch[i < 1000](i + 1);
}
void noprint(int i) { /* do nothing. */ }
int main() {
yesprint(1);
}
i <= 1000
это условие.
Задача никогда не указывала, что программа должна завершиться после 1000.
void f(int n){
printf("%d\n",n);
f(n+1);
}
int main(){
f(1);
}
(Может быть сокращено до этого, если вы запустите. /a.out без дополнительных параметров)
void main(int n) {
printf("%d\n", n);
main(n+1);
}
Легко, как пирог!: P
#include <iostream>
static int current = 1;
struct print
{
print() { std::cout << current++ << std::endl; }
};
int main()
{
print numbers [1000];
}
#include <stdio.h>
#define Out(i) printf("%d\n", i++);
#define REP(N) N N N N N N N N N N
#define Out1000(i) REP(REP(REP(Out(i))));
void main()
{
int i = 1;
Out1000(i);
}
Мы можем запустить 1000 потоков, каждый из которых печатает один из чисел. Установите OpenMPI, скомпилируйте с помощью mpicxx -o 1000 1000.cpp
и запустите с помощью mpirun -np 1000 ./1000
. Вероятно, вам нужно увеличить лимит дескриптора, используя limit
или ulimit
. Обратите внимание, что это будет довольно медленным, если у вас нет нагрузок сердечников!
#include <cstdio>
#include <mpi.h>
using namespace std;
int main(int argc, char **argv) {
MPI::Init(argc, argv);
cout << MPI::COMM_WORLD.Get_rank() + 1 << endl;
MPI::Finalize();
}
Конечно, цифры не обязательно будут напечатаны по порядку, но вопрос не требует их упорядочения.
С равным C:
#include<stdio.h>
/* prints number i */
void print1(int i) {
printf("%d\n",i);
}
/* prints 10 numbers starting from i */
void print10(int i) {
print1(i);
print1(i+1);
print1(i+2);
print1(i+3);
print1(i+4);
print1(i+5);
print1(i+6);
print1(i+7);
print1(i+8);
print1(i+9);
}
/* prints 100 numbers starting from i */
void print100(int i) {
print10(i);
print10(i+10);
print10(i+20);
print10(i+30);
print10(i+40);
print10(i+50);
print10(i+60);
print10(i+70);
print10(i+80);
print10(i+90);
}
/* prints 1000 numbers starting from i */
void print1000(int i) {
print100(i);
print100(i+100);
print100(i+200);
print100(i+300);
print100(i+400);
print100(i+500);
print100(i+600);
print100(i+700);
print100(i+800);
print100(i+900);
}
int main() {
print1000(1);
return 0;
}
Конечно, вы можете реализовать ту же идею для других баз (2: print2 print4 print8...), но число 1000 здесь предлагает основание 10. Вы также можете немного уменьшить количество строк, добавляющих промежуточные функции: print2() print10() print20() print100() print200() print1000()
и другие эквивалентные альтернативы.
B
1000 является вполне допустимым числом и всегда равно B^3
.
Просто используйте std:: copy() со специальным итератором.
#include <algorithm>
#include <iostream>
#include <iterator>
struct number_iterator
{
typedef std::input_iterator_tag iterator_category;
typedef int value_type;
typedef std::size_t difference_type;
typedef int* pointer;
typedef int& reference;
number_iterator(int v): value(v) {}
bool operator != (number_iterator const& rhs) { return value != rhs.value;}
number_iterator operator++() { ++value; return *this;}
int operator*() { return value; }
int value;
};
int main()
{
std::copy(number_iterator(1),
number_iterator(1001),
std::ostream_iterator<int>(std::cout, " "));
}
std::copy
идет немного ближе к петле.
Использовать указатель функции (ab). Нет препроцессорной магии для увеличения производительности. ANSI C.
#include <stdio.h>
int i=1;
void x10( void (*f)() ){
f(); f(); f(); f(); f();
f(); f(); f(); f(); f();
}
void I(){printf("%i ", i++);}
void D(){ x10( I ); }
void C(){ x10( D ); }
void M(){ x10( C ); }
int main(){
M();
}
#include <iostream>
#include <iterator>
using namespace std;
int num() { static int i = 1; return i++; }
int main() { generate_n(ostream_iterator<int>(cout, "\n"), 1000, num); }
Ugly C answer (разворачивается только для одного кадра стека на мощность 10):
#define f5(i) f(i);f(i+j);f(i+j*2);f(i+j*3);f(i+j*4)
void f10(void(*f)(int), int i, int j){f5(i);f5(i+j*5);}
void p1(int i){printf("%d,",i);}
#define px(x) void p##x##0(int i){f10(p##x, i, x);}
px(1); px(10); px(100);
void main()
{
p1000(1);
}
Переполнение стека:
#include <stdio.h>
static void print_line(int i)
{
printf("%d\n", i);
print_line(i+1);
}
int main(int argc, char* argv[])
{
//get up near the stack limit
char tmp[ 8388608 - 32 * 1000 - 196 * 32 ];
print_line(1);
}
Это для стека 8 МБ. Кажется, что каждый вызов функции занимает около 32 байт (следовательно, 32 * 1000). Но затем, когда я его запустил, я получил только 804 (следовательно, 196 * 32, возможно, в C runtime есть другие части в стеке, которые вы также должны вычесть).
Развлечения с указателями функций (ни один из этих новомодных TMP не нужен):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define MSB(typ) ((sizeof(typ) * CHAR_BIT) - 1)
void done(int x, int y);
void display(int x, int y);
void (*funcs[])(int,int) = {
done,
display
};
void done(int x, int y)
{
exit(0);
}
void display(int x, int limit)
{
printf( "%d\n", x);
funcs[(((unsigned int)(x-limit)) >> MSB(int)) & 1](x+1, limit);
}
int main()
{
display(1, 1000);
return 0;
}
В качестве побочного примечания: я принял запрет на условные выражения, чтобы распространиться и на логические и реляционные операторы. Если вы разрешите логическое отрицание, рекурсивный вызов можно упростить, чтобы:
funcs[!!(limit-1)](x+1, limit-1);
funcs[!!(limit-1)](x+1, limit-1);
!
и переключать элементы массива указателей на функции, но я не знаю, будет ли это хорошо сочетаться с вашим другим безумием.
Я считаю, что этот ответ будет очень простым и понятным.
int print1000(int num=1)
{
printf("%d\n", num);
// it will check first the num is less than 1000.
// If yes then call recursive function to print
return num<1000 && print1000(++num);
}
int main()
{
print1000();
return 0;
}
Я пропустил все самое интересное, все хорошие ответы на С++ уже были опубликованы!
Это самая странная вещь, которую я мог бы придумать, но я бы не стал спорить с ее законным C99: p
#include <stdio.h>
int i = 1;
int main(int argc, char *argv[printf("%d\n", i++)])
{
return (i <= 1000) && main(argc, argv);
}
Еще один, с небольшим обманом:
#include <stdio.h>
#include <boost/preprocessor.hpp>
#define ECHO_COUNT(z, n, unused) n+1
#define FORMAT_STRING(z, n, unused) "%d\n"
int main()
{
printf(BOOST_PP_REPEAT(1000, FORMAT_STRING, ~), BOOST_PP_ENUM(LOOP_CNT, ECHO_COUNT, ~));
}
Последняя идея, тот же чит:
#include <boost/preprocessor.hpp>
#include <iostream>
int main()
{
#define ECHO_COUNT(z, n, unused) BOOST_PP_STRINGIZE(BOOST_PP_INC(n))"\n"
std::cout << BOOST_PP_REPEAT(1000, ECHO_COUNT, ~) << std::endl;
}
main
результаты неопределенным поведением, насколько я помню.
Просто как пирог:
int main(int argc, char* argv[])
{
printf(argv[0]);
}
способ выполнения:
printer.exe "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;76;77;78;79;80;81;82;83;84;85;86;87;88;89;90;91;92;93;94;95;96;97;98;99;100;101;102;103;104;105;106;107;108;109;110;111;112;113;114;115;116;117;118;119;120;121;122;123;124;125;126;127;128;129;130;131;132;133;134;135;136;137;138;139;140;141;142;143;144;145;146;147;148;149;150;151;152;153;154;155;156;157;158;159;160;161;162;163;164;165;166;167;168;169;170;171;172;173;174;175;176;177;178;179;180;181;182;183;184;185;186;187;188;189;190;191;192;193;194;195;196;197;198;199;200;201;202;203;204;205;206;207;208;209;210;211;212;213;214;215;216;217;218;219;220;221;222;223;224;225;226;227;228;229;230;231;232;233;234;235;236;237;238;239;240;241;242;243;244;245;246;247;248;249;250;251;252;253;254;255;256;257;258;259;260;261;262;263;264;265;266;267;268;269;270;271;272;273;274;275;276;277;278;279;280;281;282;283;284;285;286;287;288;289;290;291;292;293;294;295;296;297;298;299;300;301;302;303;304;305;306;307;308;309;310;311;312;313;314;315;316;317;318;319;320;321;322;323;324;325;326;327;328;329;330;331;332;333;334;335;336;337;338;339;340;341;342;343;344;345;346;347;348;349;350;351;352;353;354;355;356;357;358;359;360;361;362;363;364;365;366;367;368;369;370;371;372;373;374;375;376;377;378;379;380;381;382;383;384;385;386;387;388;389;390;391;392;393;394;395;396;397;398;399;400;401;402;403;404;405;406;407;408;409;410;411;412;413;414;415;416;417;418;419;420;421;422;423;424;425;426;427;428;429;430;431;432;433;434;435;436;437;438;439;440;441;442;443;444;445;446;447;448;449;450;451;452;453;454;455;456;457;458;459;460;461;462;463;464;465;466;467;468;469;470;471;472;473;474;475;476;477;478;479;480;481;482;483;484;485;486;487;488;489;490;491;492;493;494;495;496;497;498;499;500;501;502;503;504;505;506;507;508;509;510;511;512;513;514;515;516;517;518;519;520;521;522;523;524;525;526;527;528;529;530;531;532;533;534;535;536;537;538;539;540;541;542;543;544;545;546;547;548;549;550;551;552;553;554;555;556;557;558;559;560;561;562;563;564;565;566;567;568;569;570;571;572;573;574;575;576;577;578;579;580;581;582;583;584;585;586;587;588;589;590;591;592;593;594;595;596;597;598;599;600;601;602;603;604;605;606;607;608;609;610;611;612;613;614;615;616;617;618;619;620;621;622;623;624;625;626;627;628;629;630;631;632;633;634;635;636;637;638;639;640;641;642;643;644;645;646;647;648;649;650;651;652;653;654;655;656;657;658;659;660;661;662;663;664;665;666;667;668;669;670;671;672;673;674;675;676;677;678;679;680;681;682;683;684;685;686;687;688;689;690;691;692;693;694;695;696;697;698;699;700;701;702;703;704;705;706;707;708;709;710;711;712;713;714;715;716;717;718;719;720;721;722;723;724;725;726;727;728;729;730;731;732;733;734;735;736;737;738;739;740;741;742;743;744;745;746;747;748;749;750;751;752;753;754;755;756;757;758;759;760;761;762;763;764;765;766;767;768;769;770;771;772;773;774;775;776;777;778;779;780;781;782;783;784;785;786;787;788;789;790;791;792;793;794;795;796;797;798;799;800;801;802;803;804;805;806;807;808;809;810;811;812;813;814;815;816;817;818;819;820;821;822;823;824;825;826;827;828;829;830;831;832;833;834;835;836;837;838;839;840;841;842;843;844;845;846;847;848;849;850;851;852;853;854;855;856;857;858;859;860;861;862;863;864;865;866;867;868;869;870;871;872;873;874;875;876;877;878;879;880;881;882;883;884;885;886;887;888;889;890;891;892;893;894;895;896;897;898;899;900;901;902;903;904;905;906;907;908;909;910;911;912;913;914;915;916;917;918;919;920;921;922;923;924;925;926;927;928;929;930;931;932;933;934;935;936;937;938;939;940;941;942;943;944;945;946;947;948;949;950;951;952;953;954;955;956;957;958;959;960;961;962;963;964;965;966;967;968;969;970;971;972;973;974;975;976;977;978;979;980;981;982;983;984;985;986;987;988;989;990;991;992;993;994;995;996;997;998;999;1000"
В спецификации не указывается, что последовательность должна быть сгенерирована внутри кода:)
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
class Printer
{
public:
Printer() { cout << ++i_ << "\n"; }
private:
static unsigned i_;
};
unsigned Printer::i_ = 0;
int main()
{
Printer p[1000];
}
Если принимаются решения POSIX:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
static void die(int sig) {
exit(0);
}
static void wakeup(int sig) {
static int counter = 1;
struct itimerval timer;
float i = 1000 / (1000 - counter);
printf("%d\n", counter++);
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = i; /* Avoid code elimination */
setitimer(ITIMER_REAL, &timer, 0);
}
int main() {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
signal(SIGFPE, die);
signal(SIGALRM, wakeup);
wakeup(0);
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&mutex); /* Deadlock, YAY! */
return 0;
}
Больше злоупотреблений препроцессором:
#include <stdio.h>
#define A1(x,y) #x #y "0\n" #x #y "1\n" #x #y "2\n" #x #y "3\n" #x #y "4\n" #x #y "5\n" #x #y "6\n" #x #y "7\n" #x #y "8\n" #x #y "9\n"
#define A2(x) A1(x,1) A1(x,2) A1(x,3) A1(x,4) A1(x,5) A1(x,6) A1(x,7) A1(x,8) A1(x,9)
#define A3(x) A1(x,0) A2(x)
#define A4 A3(1) A3(2) A3(3) A3(4) A3(5) A3(6) A3(7) A3(8) A3(9)
#define A5 "1\n2\n3\n4\n5\n6\n7\n8\n9\n" A2() A4 "1000\n"
int main(int argc, char *argv[]) {
printf(A5);
return 0;
}
Я чувствую себя таким грязным; Думаю, теперь я ухожу.
A2()
без такого аргумента?
#include <stdio.h>
void nothing(int);
void next(int);
void (*dispatch[2])(int) = {next, nothing};
void nothing(int x) { }
void next(int x)
{
printf("%i\n", x);
dispatch[x/1000](x+1);
}
int main()
{
next(1);
return 0;
}
Так как нет ограничений на ошибки.
int i=1; int main() { int j=i/(i-1001); printf("%d\n", i++); main(); }
Или даже лучше (?),
#include <stdlib.h>
#include <signal.h>
int i=1;
int foo() { int j=i/(i-1001); printf("%d\n", i++); foo(); }
int main()
{
signal(SIGFPE, exit);
foo();
}
volatile
в объявление j
#include <stdio.h>
typedef void (*fp) (int);
void stop(int i)
{
printf("\n");
}
void next(int i);
fp options[2] = { next, stop };
void next(int i)
{
printf("%d ", i);
options[i/1000](++i);
}
int main(void)
{
next(1);
return 0;
}
Для любителей С++
int main() {
std::stringstream iss;
iss << std::bitset<32>(0x12345678);
std::copy(std::istream_iterator< std::bitset<4> >(iss),
std::istream_iterator< std::bitset<4> >(),
std::ostream_iterator< std::bitset<4> >(std::cout, "\n"));
}
Используя арифметику указателя, мы можем использовать автоматическую инициализацию массива до 0 в наших интересах.
#include <stdio.h>
void func();
typedef void (*fpa)();
fpa fparray[1002] = { 0 };
int x = 1;
void func() {
printf("%i\n", x++);
((long)fparray[x] + &func)();
}
void end() { return; }
int main() {
fparray[1001] = (fpa)(&end - &func);
func();
return 0;
}
Нарушение препроцессора!
#include <stdio.h>
void p(int x) { printf("%d\n", x); }
#define P5(x) p(x); p(x+1); p(x+2); p(x+3); p(x+4);
#define P25(x) P5(x) P5(x+5) P5(x+10) P5(x+15) P5(x+20)
#define P125(x) P25(x) P25(x+50) P25(x+75) P25(x+100)
#define P500(x) P125(x) P125(x+125) P125(x+250) P125(x+375)
int main(void)
{
P500(1) P500(501)
return 0;
}
Предварительно обработанная программа (см. ее с помощью gcc -E input.c
) является забавной.
template <int To, int From = 1>
struct printer {
static void print() {
cout << From << endl;
printer<To, From + 1>::print();
}
};
template <int Done>
struct printer<Done, Done> {
static void print() {
cout << Done << endl;
}
};
int main()
{
printer<1000>::print();
}
Это использует только стек O (log N) и использует оценку McCarthy http://en.wikipedia.org/wiki/Short-circuit_evaluation как условие рекурсии.
#include <stdio.h>
int printN(int n) {
printf("%d\n", n);
return 1;
}
int print_range(int low, int high) {
return ((low+1==high) && (printN(low)) ||
(print_range(low,(low+high)/2) && print_range((low+high)/2, high)));
}
int main() {
print_range(1,1001);
}
Версия OpenMP (конечно не упорядоченная):
#include <iostream>
#include <omp.h>
int main(int argc, char** argv)
{
#pragma omp parallel num_threads(1000)
{
#pragma omp critical
{
std::cout << omp_get_thread_num() << std::endl;
}
}
return 0;
}
(Не работает с VS2010 OpenMP runtime (ограниченным до 64 потоков), однако работает на Linux с, например, компилятором Intel)
Здесь также упорядоченная версия:
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int i = 1;
#pragma omp parallel num_threads(1000)
#pragma omp critical
printf("%d ", i++);
return 0;
}
Никто не сказал, что после этого не следует segfault, верно?
Примечание: это работает правильно в моей 64-разрядной системе Mac OS X. Для других систем вам нужно будет изменить args на setrlimit и размер spacechew соответственно.; -)
(мне не нужно включать это, но на всякий случай: это явно не пример хорошей практики программирования. Однако у него есть то преимущество, что он использует имя этого сайта.)
#include <sys/resource.h>
#include <stdio.h>
void recurse(int n)
{
printf("%d\n", n);
recurse(n + 1);
}
int main()
{
struct rlimit rlp;
char spacechew[4200];
getrlimit(RLIMIT_STACK, &rlp);
rlp.rlim_cur = rlp.rlim_max = 40960;
setrlimit(RLIMIT_STACK, &rlp);
recurse(1);
return 0; /* optimistically */
}
Я переформулировал великую рутину, предложенную Bill, чтобы сделать ее более универсальной:
void printMe ()
{
int i = 1;
startPrintMe:
printf ("%d\n", i);
void *labelPtr = &&startPrintMe + (&&exitPrintMe - &&startPrintMe) * (i++ / 1000);
goto *labelPtr;
exitPrintMe:
}
ОБНОВЛЕНИЕ: Второй подход требует 2 функции:
void exitMe(){}
void printMe ()
{
static int i = 1; // or 1001
i = i * !!(1001 - i) + !(1001 - i); // makes function reusable
printf ("%d\n", i);
(typeof(void (*)())[]){printMe, exitMe} [!(1000-i++)](); // :)
}
В обоих случаях вы можете начать печать, просто позвонив
printMe();
Был протестирован для GCC 4.2.
Вариант C + для принятого ответа из предполагаемого дубликата:
void print(vector<int> &v, int ind)
{
v.at(ind);
std::cout << ++ind << std::endl;
try
{
print(v, ind);
}
catch(std::out_of_range &e)
{
}
}
int main()
{
vector<int> v(1000);
print(v, 0);
}
#include<stdio.h>
int b=1;
int printS(){
printf("%d\n",b);
b++;
(1001-b) && printS();
}
int main(){printS();}
#include <stdio.h> int main(int argc, char **argv) { char oh_god_no[50]; if(atoi(argv[1])==1000) return 0; sprintf(oh_god_no,"python -c \"import os; print %d; os.system('./a.out %d\')\"",atoi(argv[1])+1,atoi(argv[1])+1); system(oh_god_no); }
С макросами!
#include<stdio.h>
#define x001(a) a
#define x002(a) x001(a);x001(a)
#define x004(a) x002(a);x002(a)
#define x008(a) x004(a);x004(a)
#define x010(a) x008(a);x008(a)
#define x020(a) x010(a);x010(a)
#define x040(a) x020(a);x020(a)
#define x080(a) x040(a);x040(a)
#define x100(a) x080(a);x080(a)
#define x200(a) x100(a);x100(a)
#define x3e8(a) x200(a);x100(a);x080(a);x040(a);x020(a);x008(a)
int main(int argc, char **argv)
{
int i = 0;
x3e8(printf("%d\n", ++i));
return 0;
}
x001(a)
- это макрос, который выполняет данное действие один раз. x002(a)
выполняет x001(a)
дважды, поэтому выполняет действие дважды. x004(a)
выполняет x002(a)
дважды, поэтому выполняет данное действие 4 раза. Вещи продолжают удваиваться, пока мы не определим x3e8(a)
, который выполняет действие 1000 раз (3e8 в гексе). Дано действие printf("%d\n", ++i)
, которое увеличивает i и затем печатает его. Поэтому, когда мы передаем его в x3e8()
, поскольку макросы не передаются по значению (в отличие от функций, которые есть), действие повторяется 1000 раз, печатая все числа от 1 до 1000.
template <int remaining>
void print(int v) {
printf("%d\n", v);
print<remaining-1>(v+1);
}
template <>
void print<0>(int v) {
}
print<1000>(1);
Вы можете сделать это довольно просто, используя рекурсию и вынужденную ошибку...
Кроме того, простите мой ужасно неаккуратный код С++.
void print_number(uint number)
{
try
{
print_number(number-1);
}
catch(int e) {}
printf("%d", number+1);
}
void main()
{
print_number(1001);
}
Это также можно сделать с помощью простой динамической отправки (также работает на Java):
#include<iostream>
using namespace std;
class U {
public:
virtual U* a(U* x) = 0;
virtual void p(int i) = 0;
static U* t(U* x) { return x->a(x->a(x->a(x))); }
};
class S : public U {
public:
U* h;
S(U* h) : h(h) {}
virtual U* a(U* x) { return new S(new S(new S(h->a(x)))); }
virtual void p(int i) { cout << i << endl; h->p(i+1); }
};
class Z : public U {
public:
virtual U* a(U* x) { return x; }
virtual void p(int i) {}
};
int main(int argc, char** argv) {
U::t(U::t(U::t(new S(new Z()))))->p(1);
}
ИЗМЕНИТЬ 2:
Я удалил поведение undefined из кода. Спасибо @sehe для уведомления.
Нет циклов, рекурсий, условных выражений и всего стандартного C... (qsort abuse):
#include <stdio.h>
#include <stdlib.h>
int numbers[51] = {0};
int comp(const void * a, const void * b){
numbers[0]++;
printf("%i\n", numbers[0]);
return 0;
}
int main()
{
qsort(numbers+1,50,sizeof(int),comp);
comp(NULL, NULL);
return 0;
}
int numbers[0]
порядке? Я ожидал, что это будет неопределенное поведение в ++numbers[0]
? Если вы можете объяснить, почему это не должно быть int numbers[1];
Я был бы очень благодарен
++numbers[0]
- это UB, а сортировка несуществующих 246 элементов массива с помощью qsort - также UB. Я просто нашел опытным путем, что при использовании int numbers[1]
и qsort(numbers+1,...
-) результат получается несколько хаотичным.
Мой небольшой вклад в этот сказочный набор ответов (он возвращает ноль):
#include <stdio.h>
int main(int a)
{
return a ^ 1001 && printf("%d\n", main(a+1)) , a-1;
}
Командный оператор - FTW\o/
После некоторых мастерингов я придумал это:
template<int n>
class Printer
{
public:
Printer()
{
std::cout << (n + 1) << std::endl;
mNextPrinter.reset(new NextPrinter);
}
private:
typedef Printer<n + 1> NextPrinter;
std::auto_ptr<NextPrinter> mNextPrinter;
};
template<>
class Printer<1000>
{
};
int main()
{
Printer<0> p;
return 0;
}
Позже подача @ybungalobill вдохновила меня на эту гораздо более простую версию:
struct NumberPrinter
{
NumberPrinter()
{
static int fNumber = 1;
std::cout << fNumber++ << std::endl;
}
};
int main()
{
NumberPrinter n[1000];
return 0;
}
manglesky solution отлично, но не достаточно запутано.:-) Итак:
#include <stdio.h>
#define TEN(S) S S S S S S S S S S
int main() { int i = 1; TEN(TEN(TEN(printf("%d\n", i++);))) return 0; }
Использование макросжатия:
#include <stdio.h>
#define a printf("%d ",++i);
#define b a a a a a
#define c b b b b b
#define d c c c c c
#define e d d d d
int main ( void ) {
int i = 0;
e e
return 0;
}
Или еще лучше:
#include <stdio.h>
#define a printf("%d ",++i);
#define r(x) x x x x x
#define b r(r(r(a a a a)))
int main ( void ) {
int i = 0;
b b
return 0;
}
Вдохновленный Orion_G ответом и обсуждением reddit; использует указатели функций и двоичную арифметику:
#include <stdio.h>
#define b10 1023
#define b3 7
typedef void (*fp) (int,int);
int i = 0;
void print(int a, int b) { printf("%d\n",++i); }
void kick(int a, int b) { return; }
void rec(int,int);
fp r1[] = {print, rec} ,r2[] = {kick, rec};
void rec(int a, int b) {
(r1[(b>>1)&1])(b10,b>>1);
(r2[(a>>1)&1])(a>>1,b);
}
int main() {
rec(b10,b3);
return 1;
}
Как насчет другого аномального примера завершения. На этот раз отрегулируйте размер стека до 1000 рекурсий.
int main(int c, char **v)
{
static cnt=0;
char fill[12524];
printf("%d\n", cnt++);
main(c,v);
}
На моей машине он печатает от 1 до 1000
995
996
997
998
999
1000
Segmentation fault (core dumped)
#include<iostream>
#include<stdexcept>
using namespace std;
int main(int arg)
{
try
{
printf("%d\n",arg);
int j=1/(arg-1000);
main(arg+1);
}
catch(...)
{
exit(1);
}
}
Это стандартный C:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%d ", argc);
(void) (argc <= 1000 && main(argc+1, 0));
return 0;
}
Если вы вызываете его без аргументов, он будет печатать числа от 1 до 1000. Обратите внимание, что && оператор не является "условным утверждением", хотя он служит той же цели.
С++, использующий RAII
#include <iostream>
using namespace std;
static int i = 1;
struct a
{
a(){cout<<i++<<endl;}
~a(){cout<<i++<<endl;}
}obj[500];
int main(){return 0;}
C использование макросов
#include <stdio.h>
#define c1000(x) c5(c5(c5(c4(c2(x)))))
#define c5(x) c4(x) c1(x) //or x x x x x
#define c4(x) c2(c2(x)) //or x x x x
#define c2(x) c1(x) c1(x) //or x x
#define c1(x) x
int main(int i){c1000(printf("%d\n",i++);)return 0;}
Изменить: Еще один, этот простой
#include <stdio.h>
#define p10(x) x x x x x x x x x x
int main(int i){p10(p10(p10(printf("%d\n",i++);)))return 0;}
C, использующий recrusion
edit: этот код c содержит <= и?: operator
#include <stdio.h>
int main(int i){return (i<=1000)?main(printf("%d\n",i++)*0 + i):0;}
Что вы думаете о
int main(void) {
printf(" 1 2 3 4 5 6 7 8");
return 0;
}
Держу пари, что 1000 были в двоичном и он, очевидно, проверял парня CQ (compSci Quotient)
printf("1 ... 1000");
что противоречит правилам.
Мне интересно, изменил ли интервьюер другой вопрос: вычислите сумму чисел от 1 до 1000 (или от любых n до m) без использования цикла. Он также преподает хороший урок по анализу проблем. Печать # с 1 по 1000 в C всегда будет основываться на трюках, которые вы не можете использовать в производственной программе (хвостовая рекурсия в Main, побочные эффекты того, как вычисляется истинность, или препрок и трюки шаблонов.)
Было бы неплохо проверить, есть ли у вас какая-то математическая подготовка, потому что эта старая история о Гаусе и его решении, вероятно, будет хорошо известна всем, кто занимается математикой.
Я предполагаю, из-за характера этого вопроса, что расширения не исключены?
Кроме того, я удивлен, что до сих пор никто не использовал goto
.
int main () {
int i = 0;
void * addr[1001] = { [0 ... 999] = &&again};
addr[1000] = &&end;
again:
printf("%d\n", i + 1);
goto *addr[++i];
end:
return 0;
}
Хорошо, так что технически это цикл - но это не более цикл, чем все рекурсивные примеры до сих пор;)
Поместите 1 к 1000 в файл "файл"
int main()
{
system("cat file");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef void(*word)(int);
word words[1024];
void print(int i) {
printf("%d\n", i);
words[i+1](i+1);
}
void bye(int i) {
exit(0);
}
int main(int argc, char *argv[]) {
words[0] = print;
words[1] = print;
memcpy(&words[2], &words[0], sizeof(word) * 2); // 0-3
memcpy(&words[4], &words[0], sizeof(word) * 4); // 0-7
memcpy(&words[8], &words[0], sizeof(word) * 8); // 0-15
memcpy(&words[16], &words[0], sizeof(word) * 16); // 0-31
memcpy(&words[32], &words[0], sizeof(word) * 32); // 0-63
memcpy(&words[64], &words[0], sizeof(word) * 64); // 0-127
memcpy(&words[128], &words[0], sizeof(word) * 128); // 0-255
memcpy(&words[256], &words[0], sizeof(word) * 256); // 0-511
memcpy(&words[512], &words[0], sizeof(word) * 512); // 0-1023
words[1001] = bye;
words[1](1);
}
Удивительно, насколько легко это происходит, если вы уроните требование "должно быть в C или С++":
Unix shell:
echo {1..1000} | tr ' ' '\n'
или
yes | nl | awk '{print $1}' | head -1000
Если вы используете вариант Unix, который не имеет команды yes, используйте другой процесс, который генерирует не менее 1000 строк:
find / 2> /dev/null | nl | awk '{print $1}' | head -1000
или
cat /dev/zero | uuencode - | nl | awk '{print $1}' | head -1000
или
head -1000 /etc/termcap | nl -s: | cut -d: -f1
Используя рекурсию, условные выражения могут быть заменены с помощью арифметики указателя функции:
#include <stdio.h>
#include <stdlib.h> // for: void exit(int CODE)
// function pointer
typedef void (*fptr)(int);
void next(int n)
{
printf("%d\n", n);
// pointer to next function to call
fptr fp = (fptr)(((n != 0) * (unsigned int) next) +
((n == 0) * (unsigned int) exit));
// decrement and call either ``next'' or ``exit''
fp(n-1);
}
int main()
{
next(1000);
}
Обратите внимание, что нет никаких условий; n!=0
и n==0
являются ветвящимися операциями. (Хотя мы выполняем ветвь в хвостовом вызове).
Должно работать на любой машине, которая не нравится 0/0. Вы можете заменить это ссылкой на нулевой указатель, если вам нужно. Программа может выйти из строя после печати от 1 до 1000, правильно?
#include <stdio.h>
void print_1000(int i);
void print_1000(int i) {
int j;
printf("%d\n", i);
j = 1000 - i;
j = j / j;
i++;
print_1000(i);
}
int main() {
print_1000(1);
}
До сих пор существует множество аномальных выходов из-за, но пока нет кучи, поэтому здесь мой вклад:
#include <cstdio>
#include <cstdlib>
#include <sys/mman.h>
#include <sys/signal.h>
#define PAGE_SIZE 4096
void print_and_set(int i, int* s)
{
*s = i;
printf("%d\n", i);
print_and_set(i + 1, s + 1);
}
void
sigsegv(int)
{
fflush(stdout); exit(0);
}
int
main(int argc, char** argv)
{
int* mem = reinterpret_cast<int*>
(reinterpret_cast<char*>(mmap(NULL, PAGE_SIZE * 2, PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0)) +
PAGE_SIZE - 1000 * sizeof(int));
mprotect(mem + 1000, PAGE_SIZE, PROT_NONE);
signal(SIGSEGV, sigsegv);
print_and_set(1, mem);
}
Не очень хорошая практика и отсутствие ошибок (по понятным причинам), но я не думаю, что это вопрос!
Есть много других аномальных вариантов завершения, конечно, некоторые из них более простые: assert(), SIGFPE (я думаю, кто-то сделал это) и т.д.
#include <stdio.h>
#include <stdlib.h>
void print(int n)
{
int q;
printf("%d\n", n);
q = 1000 / (1000 - n);
print(n + 1);
}
int main(int argc, char *argv[])
{
print(1);
return EXIT_SUCCESS;
}
В конечном итоге он остановится: P
Мне не нравится ломать его, но рекурсия и цикл - это, по сути, одно и то же на уровне машины.
Разница заключается в использовании JMP/JCC в сравнении с инструкцией CALL. Оба из них имеют примерно одинаковое время цикла и очищают конвейер команд.
Моим любимым трюком для рекурсии было ручной код PUSH обратного адреса и использование JMP для функции. Функция тогда ведет себя нормально и возвращается в конце, но куда-то еще. Это действительно полезно для синтаксического анализа быстрее, потому что это уменьшает поток конвейера.
Оригинальный плакат, вероятно, собирался либо для полного разворота, которое разработали парни шаблонов; или памяти страниц в терминал, если вы точно знаете, где хранится текст терминала. Последнее требует много проницательности и рискованно, но почти не имеет вычислительной мощности, и код не содержит гадостей, например 1000 печатных изданий.
COME FROM
для C ?!
Ни цикл, ни условные выражения и, по крайней мере, он не падает на моей машине:). Используя магию указателя, мы имеем...
#include <stdlib.h>
#include <stdio.h>
typedef void (*fp) (void *, int );
void end(fp* v, int i){
printf("1000\n");
return;
}
void print(fp *v, int i)
{
printf("%d\n", 1000-i);
v[i-1] = (fp)print;
v[0] = (fp)end;
(v[i-1])(v, i-1);
}
int main(int argc, char *argv[])
{
fp v[1000];
print(v, 1000);
return 0;
}
Вам не нужно ничего больше, чем базовая обработка строк:
#include <iostream>
#include <algorithm>
std::string r(std::string s, char a, char b)
{
std::replace(s.begin(), s.end(), a, b);
return s;
}
int main()
{
std::string s0 = " abc\n";
std::string s1 = r(s0,'c','0')+r(s0,'c','1')+r(s0,'c','2')+r(s0,'c','3')+r(s0,'c','4')+r(s0,'c','5')+r(s0,'c','6')+r(s0,'c','7')+r(s0,'c','8')+r(s0,'c','9');
std::string s2 = r(s1,'b','0')+r(s1,'b','1')+r(s1,'b','2')+r(s1,'b','3')+r(s1,'b','4')+r(s1,'b','5')+r(s1,'b','6')+r(s1,'b','7')+r(s1,'b','8')+r(s1,'b','9');
std::string s3 = r(s2,'a','0')+r(s2,'a','1')+r(s2,'a','2')+r(s2,'a','3')+r(s2,'a','4')+r(s2,'a','5')+r(s2,'a','6')+r(s2,'a','7')+r(s2,'a','8')+r(s2,'a','9');
std::cout << r(r(s1,'a',' '),'b',' ').substr(s0.size())
<< r(s2,'a',' ').substr(s0.size()*10)
<< s3.substr(s0.size()*100)
<< "1000\n";
}
Не знаю достаточно C (++) для написания кода, но вы можете использовать рекурсию вместо цикла. Чтобы избежать этого условия, вы можете использовать структуру данных, которая выдает исключение после 1000-го доступа. Например. какой-то список с проверкой диапазона, где вы увеличиваете/уменьшаете индекс на каждой рекурсии.
Судя по комментариям, в С++ нет каких-либо списков rangechecking?
Вместо этого вы могли бы 1/n, когда n было параметром для вашей рекурсивной функции, которая уменьшается на 1 при каждом вызове. Начните с 1000. Исключение DivisionByZero остановит вашу рекурсию
range checking
, которая потребует условного.
#include "stdafx.h"
static n=1;
class number {
public:
number () {
std::cout << n++ << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
number X[1000];
return 0;
}
Я прочитал все эти ответы, и мой отличается от всех остальных. Он является стандартным C и использует целочисленное деление для выбора указателей функций из массива. Кроме того, он компилируется и выполняется правильно без предупреждений и даже пропускает "шину" без предупреждений.
Я был, конечно, вдохновлен многими другими ответами здесь. Тем не менее, мне лучше.
#include <stdio.h>
#include <stdlib.h>
static int x(/*@unused@*/ const char * format, ...) { exit(0); }
static void p(int v, int e) {
static int (*a[])(const char *, ...) = { printf, x };
(void)a[v/(e+1)]("%d\n", v);
p(v+1, e);
}
int main(void) {
p(1, 1000);
return 0;
}
#include <iostream>
using namespace std;
template<int N>
void func()
{
func<N-1>();
cout << N << "\t";
}
template<>
void func<1>()
{
cout << 1 << "\t";
}
int main()
{
func<1000>();
cout << endl;
return 0;
}
Несмотря на весь блестящий код, увиденный здесь, я считаю, что единственный реальный ответ заключается в том, что его невозможно сделать.
Почему? Просто. Каждый ответ, по сути, зацикливается. Зацикливание замкнуто, поскольку рекурсия по-прежнему зацикливается. Один взгляд на код сборки показывает этот факт. Даже чтение и печать текстового файла с номерами включает в себя цикл. Снова посмотрим на машинный код. Впечатывание 1000 утверждений printf также означает цикл, потому что сам printf имеет в нем циклы.
Невозможно выполнить.
Здесь версия, которая использует setjmp/longjmp, потому что кто-то должен был это сделать:
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
void print(int i) {
printf("%d\n", i);
}
typedef void (*func_t)(int);
int main() {
jmp_buf buf;
func_t f[] = {print, exit};
int i = setjmp(buf)+1;
f[i/1001](i);
longjmp(buf, i);
return 0;
}
Предполагая, что программа запускается обычным способом (./a.out), так что она имеет один аргумент и игнорирует предупреждения типа компилятора:
#include <stdio.h>
#include <stdlib.h>
void main(int i) {
static void (*cont[2])(int) = { main, exit };
printf("%d\n", i);
cont[i/1000](i+1);
}
Если ваш компилятор C поддерживает блоки, вы можете написать следующее:
#include <stdio.h>
void ten(void (^b)(void)) { b();b();b();b();b();b();b();b();b();b(); }
int main() {
__block int i = 0;
ten(^{
ten(^{
ten(^{
printf("%d\n", ++i);
});
});
});
return 0;
}
#include <stdio.h>
int main(int argc, char** argv)
{
printf("numbers from 1 to 1000\n");
}
#include <stdio.h>
#include <assert.h>
void foo( int n )
{
printf("%d\n", n);
assert( n > 0 );
foo(--n);
}
int main()
{
foo( 1000 );
getchar();
}
#include <stdio.h>
int show(int i) {
printf("%d\n",i);
return( (i>=1000) || show(i+1));
}
int main(int argc,char **argv) {
return show(1);
}
|| оператор коротко замыкает рекурсивный вызов, чтобы показать, когда i > 1000.
Вот мои 2 решения. Сначала С#, а второй - в C:
С#:
const int limit = 1000;
Action<int>[] actions = new Action<int>[2];
actions[0] = (n) => { Console.WriteLine(n); };
actions[1] = (n) => { Console.WriteLine(n); actions[Math.Sign(limit - n-1)](n + 1); };
actions[1](0);
С
#define sign(x) (( x >> 31 ) | ( (unsigned int)( -x ) >> 31 ))
void (*actions[3])(int);
void Action0(int n)
{
printf("%d", n);
}
void Action1(int n)
{
int index;
printf("%d\n", n);
index = sign(998-n)+1;
actions[index](++n);
}
void main()
{
actions[0] = &Action0;
actions[1] = 0; //Not used
actions[2] = &Action1;
actions[2](0);
}
Здесь вариант POSIX с использованием сигналов:
#include <stdio.h>
#include <signal.h>
void counter(int done)
{
static int i;
done = ++i / 1000;
printf("%d\n", i);
signal(SIGINT, (void (*)(int))(done * (int)SIG_DFL + (1-done) * (int)&counter));
raise(SIGINT);
}
int main()
{
signal(SIGINT, &counter);
raise(SIGINT);
return 0;
}
Интересной частью является вызов counter() для сигнала(). Здесь установлен новый обработчик сигналов: SIG_DFL, если "done" is true, & counter в противном случае.
Чтобы сделать это решение еще более нелепым, я использовал требуемый обработчик сигнала, чтобы сохранить результат временного вычисления. Как побочный эффект, раздражающее предупреждение "неиспользуемая переменная" исчезает при компиляции с помощью gcc -W -Wall.
#include <stdio.h>
static void (*f[2])(int);
static void p(int i)
{
printf("%d\n", i);
}
static void e(int i)
{
exit(0);
}
static void r(int i)
{
f[(i-1)/1000](i);
r(i+1);
}
int main(int argc, char* argv[])
{
f[0] = p;
f[1] = e;
r(1);
}
pre
и code
и улучшил форматирование кода.
Если вы не возражаете против ведущих нулей, тогда давайте пропустим printf
#include <stdlib.h>
void l();
void n();
void (*c[3])() = {l, n, exit};
char *a;
void (*x)();
char b[] = "0000";
void run() { x(); run(); }
#define C(d,s,i,j,f) void d() { s;x = c[i]; a = j;f; }
C(l, puts(b), 1+(a<b), b+3,)
C(n, int v = *a - '0' + 1; *a = v%10 + '0', v/10, a-1,)
C(main,,1,b+3, run())
Как это ответ:)
printf("numbers from 1 to 1000 without using any loop or conditional statements. Don't just write the printf() or cout statement 1000 times.");
выставить концепцию С++, передать gcc, vc
[root@localhost ~]# cat 1.cpp
#include <stdio.h>
#include <stdlib.h>
int i = 1;
void print(int arg0)
{
printf("%d ",i);
*(&arg0 - 1) = (int)print;
*(&arg0 - i/1000) = (int)exit;
i++;
}
int main(void) {
int a[1000];
print(0);
return 0;
}
Запуск:
[root@localhost ~]# g++ 1.cpp -o 1
[root@localhost ~]# ./1
1 2 ... 1000
Трудно увидеть все решения, которые уже были предложены, поэтому, возможно, это дубликат.
Я хотел иметь что-то относительно просто с чистым C, а не с С++. Он использует рекурсию, но, вопреки другим решениям, которые я видел, это только рекурсия логарифмической глубины. Использование условных выражений исключается путем поиска таблицы.
typedef void (*func)(unsigned, unsigned);
void printLeaf(unsigned, unsigned);
void printRecurse(unsigned, unsigned);
func call[2] = { printRecurse, printLeaf };
/* All array members that are not initialized
explicitly are implicitly initialized to 0
according to the standard. */
unsigned strat[1000] = { 0, 1 };
void printLeaf(unsigned start, unsigned len) {
printf("%u\n", start);
}
void printRecurse(unsigned start, unsigned len) {
unsigned half0 = len / 2;
unsigned half1 = len - half0;
call[strat[half0]](start, half0);
call[strat[half1]](start + half0, half1);
}
int main (int argc, char* argv[]) {
printRecurse(0, 1000);
}
Это можно сделать даже динамически, используя только указатель. Соответствующие изменения:
unsigned* strat = 0;
int main (int argc, char* argv[]) {
strat = calloc(N, sizeof(*strat));
strat[1] = 1;
printRecurse(0, N);
}
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/lambda/lambda.hpp>
#include <iostream>
int main()
{
boost::mpl::for_each<boost::mpl::range_c<unsigned, 1, 1001> >(std::cout << boost::lambda::_1 << '\n');
return(0);
}
system("/usr/bin/env echo {1..1000}");
static void Main(string[] args)
{
print(1000);
System.Console.ReadKey();
}
static bool print(int val)
{
try
{
print( ((val/val)*val) - 1);
System.Console.WriteLine(val.ToString());
}
catch (Exception ex)
{
return false;
}
return true;
}
Примечание:
Тогда
#include <iostream>
#include <ctime>
#ifdef _WIN32
#include <windows.h>
#define sleep(x) Sleep(x*1000)
#endif
int main() {
time_t c = time(NULL);
retry:
sleep(1);
std::cout << time(NULL)-c << std::endl;
goto retry;
}
Javascript загружается для удовольствия. Включает автоматическую остановку при 1000:
var max = 1000;
var b = ["break"];
function increment(i) {
var j = Math.abs(i - max);
console.log(j);
b[(i/i) - 1].toString();
i--;
increment(i);
}
increment(max);
#include <stdio.h>
int main() { printf("numbers from 1 to 1000"); return 0; }
Это как эта другая загадка об английских словах, которые заканчиваются на "играх", правильно?.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
void (*f[2])(int v);
void p(int v)
{
printf("%d\n", v++);
f[(int)(floor(pow(v, v - 1000)))](v);
}
void e(int v)
{
printf("%d\n", v);
}
int main(void)
{
f[0] = p;
f[1] = e;
p(1);
}
Если вы собираетесь использовать рекурсию во время компиляции, то вы, вероятно, также захотите использовать divide и conquer, чтобы не нажимать пределы глубины шаблона:
#include <iostream>
template<int L, int U>
struct range
{
enum {H = (L + U) / 2};
static inline void f ()
{
range<L, H>::f ();
range<H+1, U>::f ();
}
};
template<int L>
struct range<L, L>
{
static inline void f ()
{
std::cout << L << '\n';
}
};
int main (int argc, char* argv[])
{
range<1, 1000>::f ();
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
#define N 10 //10 or 1000, doesn't matter
class A{
public:
A(){
//cout << "A(): " << m_ << endl; //uncomment to show the difference between gcc and Microsoft C++ compiler
}
A(const A&){
++m_;
cout << m_ << endl;
}
private:
static int m_; //global counter
};
int A::m_(0); //initialization
int main(int argc, char* argv[])
{
//Creates a vector with N elements. Printing is from the copy constructor,
//which is called exactly N times.
vector<A> v(N);
return 0;
}
Замечание по реализации:
С gcc: Один конструктор "master" создается конструктором по умолчанию.
Затем элемент копируется N раз с помощью конструктора копирования.
С компилятором Microsoft С++: все элементы создаются конструктором по умолчанию
а затем копируется с помощью конструктора копирования.
Простая версия C, заканчивается на 1000:
int print_stuff(int count) {
printf("%d\n", count);
return (count ^ 1000) && print_stuff(count+1);
}
int main(int argc, char *argv[]) {
print_stuff(1);
return 0;
}
Очевидно, что требуется Windows/Visual Studio... Но он работает.
#include <stdio.h>
#include <Windows.h>
void print(int x)
{
int y;
printf("%d\n", x);
__try
{
y = 1 / (x - 1000);
print(x + 1);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return;
}
}
void main()
{
print(1);
}
Возможно, это слишком очевидно и легко следовать, но это стандартный С++, не сбрасывает стек и работает в O (n) время с использованием O (n) памяти.
#include <iostream>
#include <vector>
using namespace std;
int main (int argc, char** args) {
vector<int> foo = vector<int>(1000);
int terminator = 0;
p:
cout << terminator << endl;
try {
foo.at(terminator++);
} catch(...) {
return 0;
}
goto p;
}
#include <stdio.h>
void main(int i){printf("%d\n",i)&&i++<1000&&(*((int*)&i-1)-=5);}
другой:
#include <stdio.h>
int main(int i){return i<=1000&&printf("%d\n",i)&&main(++i);}
грязный код: s
используется xor и массив указателей функций.
#include <stdio.h>
#include <stdlib.h>
typedef void (*fn)(int);
int lst[1001];
void print (int n)
{
printf ("%d ", n+1);
go (n+1);
}
void go (int n)
{
((fn)(((long)print)^((long)lst[n])))(n);
}
int main ()
{
lst[1000] = ((long)print)^((long)exit);
go (0);
}
Я думаю, что этот код работает совершенно правильно, и его легко понять, что вы можете распечатать любые значения от 1 до 100 или 1 до конечного диапазона. просто поместите его в я и перенесите его на функцию вызова.
int main()
{
int i=1;
call(i,i);
}
void call(int i,int j)
{
printf("%d",i);
sleep(1); // to see the numbers for delay
j /= (j-1000);
j = ++i;
call(i,j);
}
поэтому, когда j равно 1000, он получает деление на ноль, и он непосредственно выходит из программы, что моя идея печатать числа
или гораздо более простой код.
int main()
{
static int i = 1;
static int j = 1;
printf("%d", i);
sleep(1);
j = ++i;
j /= (j-1000);
main();
}
call()
в первом блоке, вызов main()
во втором блоке (вы не можете вызывать main()
внутри вашей программы) ,
Вы можете использовать System()
для печати от 1 до 1000 (с помощью с помощью команды DOS)
include <process.h>
void main()
{
system("cmd.exe /c for /l %x in (1, 1, 1000) do echo %x" );
}
Запустите .exe(исполняемый файл) файл вашей программы, который отображает от 1 до 1000
ПРИМЕЧАНИЕ. Протестировано в WINDOWS
Я не думаю, что это "трюк"., "?:" не является условным, это оператор.
Итак, используйте рекурсию и оператор?: чтобы определить, когда остановиться?
int recurse(i)
{
printf("%d\n", i);
int unused = i-1000?recurse(i+1):0;
}
recurse(1);
Или вдоль подобной извращенной линии мышления., второе предложение в "&" условие выполняется только в том случае, если первое значение истинно. Итак, перезапишите что-то вроде этого:
i-1000 & recurse(i+1);
Возможно, интервьюер считает, что выражение вместо условного.
?:
считается условным.
Я не собираюсь писать код, а только идею. Как сделать поток, который печатает число в секунду, а затем другой поток убивает первый поток через 1000 секунд?
Примечание: первый поток генерирует числа рекурсией.
one number per second
.
рекурсии?
#include<stdio.h>
#define MAX 1000
int i = 0;
void foo(void) {
if(i <= 1000) {
printf("%d", i);
i++;
}
}
int main (void) {
foo();
}
вы можете использовать рекурсию.
вот так:
void Print(int n)
{
cout<<n<<" ";
if(n>1000)
return
else
return Print(n+1)
}
int main ()
{
Print(1);
}
printf
и печатать два числа каждый раз, нет?