Stampa da 1 a 1000 senza loop o condizionali


323

Attività : stampare numeri da 1 a 1000 senza utilizzare alcun ciclo o istruzioni condizionali. Non limitarti a scrivere la dichiarazione printf()o cout1000 volte.

Come lo faresti usando C o C ++?


137
La risposta ovvia è usare 500 chiamate printfe stampare due numeri ogni volta, no?
James McNellis,

433
printf ("numeri da 1 a 1000");
jondavidjohn,

7
:?non è un'affermazione condizionale (è un'espressione) ...
Chris Lutz il

127
L'intervista è la tua occasione per brillare. Digli "Senza loop o condizionali? Gioco da ragazzi. Posso farlo senza un computer!" Quindi estrarre penna e blocco note. Possono darti un aspetto confuso, ma spiegano semplicemente che se non puoi contare su costrutti di linguaggio integrati, non puoi davvero assumere nulla.
JohnFx,

8
Personalmente, penso che ci siano state diverse risposte con soluzioni intelligenti e interessanti. Penso anche che, sebbene questa possa essere facilmente una terribile domanda di intervista, potrebbe esserci un buon valore in essa, purché l'intervistatore non stia davvero cercando una soluzione completamente ben formata, ma cercando se l'intervistato ha preso in considerazione approcci che indicano una conoscenza di TMP o l'uso di costrutti in modi insoliti. Penso che sarebbe male se questo fosse usato come una pura domanda "capito bene / sbagliato", ma se fosse usato come punto di partenza di una discussione, vedrei molto valore.
Michael Burr,

Risposte:


785

Compila la ricorsione del tempo! : 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);
}

8
Qualcuno può spiegarmi come funziona? molto impressionante.
Gath

28
@Zack: diventiamo reali, stiamo stampando 1.000 righe da un programma scritto per evitare deliberatamente loop. Le prestazioni non sono un problema.
dreamlax,

42
Per quelli abbastanza curiosi da compilare questo: in g ++, impostare -ftemplate-depth-1000. Il massimo di ricorsione del modello predefinito è 500.
Tom

6
Questo utilizza ancora condizionali: la corrispondenza del modello è un if glorificato.
David K.

10
@dreamlax: è solo una di quelle cose che ho imparato dall'esperienza nel corso degli anni: usare a '\n'meno che tu non voglia davvero svuotare, usare a ++imeno che tu non abbia effettivamente bisogno del valore precedente i, passare per constriferimento a meno che tu non abbia una buona ragione per non ... Quando gli sviluppatori smettono di pensarci (o non iniziano nemmeno), prima o poi si imbatteranno in un problema in cui ciò conta, solo che non sapevano nemmeno che c'erano punti in cui poteva importare.
sabato

1195

Questo in realtà si compila in assembly che non ha alcun condizionale:

#include <stdio.h>
#include <stdlib.h>

void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}


Modifica: Aggiunto '&' in modo che considererà l'indirizzo evitando gli errori del puntatore.

Questa versione di quanto sopra nella norma C, poiché non si basa sull'aritmetica sui puntatori a funzioni:

#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);
}

17
Bene, il codice in questa risposta non è ovviamente né C né C ++, quindi va bene solo se eliminiamo il requisito. Quindi qualsiasi risposta può qualificarsi perché un compilatore ipotetico potrebbe semplicemente produrre il programma richiesto da qualsiasi input.
eq-

321
@PP, questo è abbastanza lungo da spiegare, ma fondamentalmente jè inizialmente 1perché è in realtà argc, che è 1se il programma viene chiamato senza argomenti. Quindi, j/1000è 0fino a quando jdiventa 1000, dopo di che lo è 1. (exit - main)è, ovviamente, la differenza tra gli indirizzi di exit()e main(). Ciò significa che (main + (exit - main)*(j/1000))è main()fino a quando jdiventa 1000, dopo di che diventa exit(). Il risultato finale è che main()viene chiamato all'avvio del programma, quindi si chiama ricorsivamente 999 volte durante l'incremento j, quindi chiama exit(). Accidenti :)
Frédéric Hamidi,

7
Questo è uno degli abusi più sorprendenti di CI che abbia mai visto. Ma funzionerà su tutte le piattaforme?
Qwertie,

13
@Mark: questa è una firma non standard di main, non è possibile chiamare main in modo ricorsivo e il risultato della sottrazione dei puntatori a funzioni non è definito.
Yakov Galka,

9
Sì, sì, non è un codice C ++ strettamente legale per le ragioni fornite da @ybungalobill, ma devo fare +1 per pura follia e per il fatto che si compili e funzioni su alcune piattaforme. Ci sono momenti in cui la risposta corretta a "Ma non è standard!" è "Chi se ne frega!" :)
j_random_hacker il

544
#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; }

Sono sorpreso che nessuno sembra aver pubblicato questo - ho pensato che fosse il modo più ovvio. 1000 = 5*5*5*8.


Le persone hanno pubblicato questo. Le altre versioni passano il numero da stampare invece di usare un globale, ma è essenzialmente la stessa soluzione.
Chris Lutz,

1
@ Chris, usano la stessa logica espressa in macro o template, facendo esplodere la dimensione del codice, giusto? Potresti anche generare la stringa di output stessa invece di mille printfs.
Darius Bacon,

Oh sì, vedo che la risposta di Keith genera l'intera stringa, bella. :) Ho perso questo.
Darius Bacon,

43
Bene, bello sforzo, ma piuttosto strano che non hai scomposto 8 in 2 * 2 * 2 e quindi hai utilizzato la fattorizzazione primaria unica
David Heffernan,

298

Sembra che non sia necessario utilizzare i loop

printf("1 10 11 100 101 110 111 1000\n");

1
si potrebbe obiettare che l'uso copyè barare
John Dibling il

13
@Johannes in realtà sono abbastanza sicuro che printfabbia un ciclo: p
icecrime

1
@litb: Nota che non ho detto che "usare copy è barare"
John Dibling il

2
@Giovanni: copiare è barare. ne dubiti? : P
Nawaz,

1
su una scala da 1 a 10, qual è la possibilità che sto usando binario?
Giordania,

270

Ecco tre soluzioni che conosco. Il secondo potrebbe essere discusso però.

// 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
}

[ Modifica: (1) e (4) possono essere usati solo per le costanti di tempo di compilazione, (2) e (3) possono essere usati anche per le espressioni di runtime - fine modifica. ]


5
Inoltre, direi che un corto circuito non è un condizionale ... Non un'affermazione, vera, ma un'espressione condizionale, direi. A condizione che definiamo un'espressione condizionale come "qualcosa che produce salti condizionati nell'assemblatore".
Kos,

5
Domanda che mi ha colpito durante la lettura di quella del costruttore: lo standard impone che ogni elemento dell'array sia costruito in sequenza? Poco importa se il costruttore avesse effetti collaterali. Sono sicuro che ogni compilatore sano di mente lo implementa come un ciclo 0-> 1000, ma mi chiedo se potresti ancora essere conforme e tornare indietro ...
Joseph Garvin,

6
@Joseph - Il costruttore non dovrebbe essere influenzato dall'ordine in cui vengono avviati i singoli oggetti, ma è una buona domanda.
Chris Lutz,

12
@Joseph questo è definito da 12.6 / 3 (C ++ 03). L'inizializzazione viene eseguita in ordine di abbonamento.
Johannes Schaub - 2

2
@Joseph: E sono anche distrutti in ordine inverso, quindi potresti usare un distruttore altrettanto facilmente :)
j_random_hacker

263

Non sto scrivendo la dichiarazione printf 1000 volte!

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");

Prego ;)


223
Spero che tu abbia scritto un programma per generare quella riga.
Martin York,

32
open ("1000.c", 'w'). write ('printf ("% s");'% ("\ n" .join ([str (x) per x in xrange (1.1000)]) ))
Tyler Eaves il

53
Spero che il programma che hai scritto per generare quella riga non contenga loop!
Jeeyoung Kim

20
Una macro Vim farebbe il lavoro rapidamente.
StackedCrooked

2
Un po 'di Perl lo genera in modo elegante:$r='printf("'; for (1..1000) { $r.="$_\\n" } $r.='");'; print $r;
sidyll

213
printf("%d\n", 2);
printf("%d\n", 3);

Non stampa tutti i numeri, ma "Stampa numeri da 1 a 1000". Domanda ambigua per la vittoria! :)


77
il mio preferito dopo 'printf ("numeri da 1 a 1000")' - le domande stupide richiedono risposte sciocche.
SEngstrom,

Questo e spettacolare. +1 per sfruttare l'ambiguità nella domanda. haha
Nawaz,

2
Modificato; in nessun modo, forma o forma questo codice print "Print numbers from 1 to 1000."- domanda ambigua per la vittoria, descrizioni imprecise fanno schifo :)
visto il

Wow, c'è stato un po 'di vandalismo sulle risposte a questa domanda ultimamente. Qualcosa mi dice che dovremmo aggiornare quel blocco a un blocco storico.
BoltClock

172

Attiva un errore fatale! Ecco il file, 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);
}

Compilare, quindi eseguire su un prompt della shell:

$ ./countup
1
2
3
...
996
997
998
999
1000
Floating point exception
$

Questo in effetti stampa i numeri da 1 a 1000, senza loop o condizionali!


43
dovresti chiamare fflush (stdout); dopo ogni printf () ... Quando un programma si arresta in modo anomalo non è garantito che il buffer di output verrà stampato sullo schermo.
zakk,

10
@zakk: non è strettamente necessario - per impostazione predefinita stdout è bufferizzato in linea, quindi \nsarà sufficiente per svuotare l'output.
psmears,

24
stdout ha un buffer di linea se può essere determinato come dispositivo interattivo , altrimenti è completamente bufferizzato. Se il professore reindirizza stdout su un file per il controllo automatico,
fallirai

pericolo di stackoverflow (ad esempio in un ambiente incorporato)
Hernán Eche,

166

Utilizzando i comandi di sistema:

system("/usr/bin/seq 1000");

15
Un'alta probabilità /usr/bin/sequtilizza un ciclo internamente. :)

@jokester: vuoi dire, perché Solaris / BSD non ha sequn'utilità (nella configurazione predefinita)? <grin />
vedi il

Odio dirlo (beh, no non lo faccio), ma c'è un bug nella tua soluzione. Non stampa il giusto numero di numeri. :) Ecco la soluzione: system("/bin/echo {1..1000}"); se solo tu avessi scritto prima il test unitario ...
Don Branson il

1
Qualcuno intelligente ha deciso di cambiare la mia risposta, quindi non è un mio errore.
Moinudin,

100

Non testato, ma dovrebbe essere lo standard C vaniglia:

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);
}

29
@Prasoon: è una relazione.
Yakov Galka,

28
il requisito è "no conditionals" (if, switch, ecc.). non "nessuna condizione"
jon_darkstar

32
<non è una condizione. È un operatore relazionale. if/ elseè un'istruzione condizionale. ?:è un operatore condizionale. <è solo un operatore che restituisce un valore booleano. Probabilmente è una singola istruzione della macchina senza salti o altro.
Chris Lutz,

12
@ Chris Lutz: su sistemi x86, è 3 Istruzioni: cmpl, setle, e movzbl. x86-64 è quello più a cltq. PowerPC è di 2 istruzioni: cmpwie crnot.
Adam Rosenfield,

4
1 - i / 1000. Nessun confronto!
Thai

96

Un po 'noioso rispetto ad altri qui, ma probabilmente quello che stanno cercando.

#include <stdio.h>

int f(int val) {
    --val && f(val);
    return printf( "%d\n", val+1);
}

void main(void) {
    f(1000);
}

Reso più corto. impostare i = 1 all'esterno di main e quindi all'interno di main: printf ("% d \ n", 11 - i) && --i && main (i);
jftuga,

3
@Jens Schauder: approfittando della &&valutazione pigra nella prima riga di f().
Rafał Dowgird,

10
Questo non è noioso, è semplice. Se riesci a fare la stessa cosa con una breve funzione possibile con un enorme pasticcio di template template, allora dovresti farlo con la funzione :)
amertune

21
Il && è un condizionale. Un AND matematico valuterà entrambe le parti (come invece fa Java e Ada "AND"). && valuterà il secondo operatore solo se (eccolo) il primo è vero. O altro esempio: in Ada l'operatore di cortocircuito è chiamato "OPPURE", usando THEN per indicare l'aspetto condizionale. Spiacenti, avresti potuto usare altrettanto bene il? : operatore.
Martin,

Non c'è bisogno di scusarsi. && è un operatore di confronto. L'operatore ternario è un condizionale.
Aaron,

71

L'attività non ha mai specificato che il programma deve terminare dopo 1000.

void f(int n){
   printf("%d\n",n);
   f(n+1);
}

int main(){
   f(1);
}

( Può essere abbreviato in questo modo se si esegue ./a.out senza parametri aggiuntivi )

void main(int n) {
   printf("%d\n", n);
   main(n+1);
}

Tuttavia, non si ferma a 1000. Continua così.
Remy Lebeau,

Può essere abbreviato solo se si elimina il requisito di C o C ++. Quindi qualsiasi "programma" farà, perché un compilatore teorico potrebbe generare il programma desiderato (da qualsiasi input).
eq-

@eq Ancora una volta, questo si compila e funziona bene ...
Mark McDonald

72
Come ripensamento: possiamo persino eludere la matematica apparente . Se impieghiamo rand(), stamperemo tutti questi numeri da 1 a 1000. Eventualmente =: P

5
@pooh: non necessariamente, poiché rand () ha la possibilità di ripetersi dopo una certa sequenza e quella sequenza potrebbe non rientrare nella soluzione impostata per questo problema
dchhetri

71

Facile come una torta! : P

#include <iostream>

static int current = 1;

struct print
{
    print() { std::cout << current++ << std::endl; }
};

int main()
{
    print numbers [1000];
}

potresti voler fare "static int current = 0" altrimenti stampa dal 2 al 1001.
Shinnok,

ho cambiato ++ da corrente a corrente ++
Zelix

65
#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);
}

3
Ummmm. Macro. È per cena.
EvilTeach

42

Siamo in grado di lanciare 1000 thread, ognuno dei quali stampa uno dei numeri. Installare OpenMPI , compilare utilizzando mpicxx -o 1000 1000.cpped eseguire utilizzando mpirun -np 1000 ./1000. Probabilmente dovrai aumentare il limite del descrittore usandolimit o ulimit. Nota che questo sarà piuttosto lento, a meno che tu non abbia un sacco di core!

#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();
}

Naturalmente, i numeri non saranno necessariamente stampati in ordine, ma la domanda non richiede che vengano ordinati.


1
Ciclo implicito nella libreria? Ma +1 comunque per un nuovo approccio.
Chris Lutz,

11
@Chris La maggior parte delle soluzioni non ha un circuito nascosto da qualche parte?
Moinudin,

Suppongo che se prendi l'approccio "loop nel compilatore". Poiché (al di fuori di un possibile ciclo sugli argomenti in MPI::Init()) non riesco a immaginare alcun loop nell'effettivo binario del tuo programma 1000.cpp, ti ho dato un +1, anche se ci sono sicuramente dei loop in esecuzione quando lo esegui.
Chris Lutz,

40

Con semplice 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;
}

Ovviamente, puoi implementare la stessa idea per altre basi (2: print2 print4 print8 ...) ma il numero 1000 qui suggerisce la base 10. Puoi anche ridurre un po 'il numero di righe aggiungendo funzioni intermedie: print2() print10() print20() print100() print200() print1000()e altre alternative equivalenti.


Perché il numero 1000 suggerisce la base 10? In qualsiasi notazione posizionale con base B, 1000 è un numero perfettamente valido e sempre uguale B^3.
Filippo,

Volevo solo dire che, dato come il numero è rappresentato nella base 10, la fattorizzazione "10x10x10" si è suggerita, ma che sono possibili altre alternative. Immagino che avrei dovuto dire "fattorizzazione" anziché "base"
leonbloy il

34

Basta usare std :: copy () con un iteratore speciale.

#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, " "));
}

Penso che il tuo codice inizi da 0. Anche d'accordo con Chris, la domanda come l'ho vista anni fa è stata dichiarata "senza librerie tranne IO". ancora +1 :)
Yakov Galka il

3
@Chris Lutz: L'implementazione della copia non è definita. Potrei anche usare il codice modello come sopra (tu non lo sai). Quindi non puoi dire che utilizza un loop perché non lo sappiamo.
Martin York,

7
In realtà, il mio pignolo non sarebbe il ciclo implicito in std::copyquanto il condizionale implicito nel operator !=(). Indipendentemente da ciò, è una visione intelligente dell'elaborazione di una gamma e approcci intelligenti sono ciò che cerco in risposta a domande come questa.
Michael Burr,

l'implementazione specifica non è definita
selvaiyyamperumal,

@selvaiyyamperumal: Non sono sicuro di cosa stia parlando. Ma se stai parlando di comportamento, lo standard non è d'accordo con te. "Comportamento definito dall'implementazione" significa che è ben definito ma deve essere esplicitamente documentato dall'implementazione. "Comportamento indefinito" significa che può succedere di tutto.
Martin York,

33

Uso del puntatore a funzione (ab). Nessuna magia del preprocessore per aumentare l'output. 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();
}

3
Questo è quello a cui stavo pensando. Una persona precedente ha detto che 5 * 5 * 5 * 8 = 1000. Ho pensato che fosse divertente che gli mancasse l'ovvio 10 ^ 3. Bella soluzione!
Evan Moran,

32
#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); }

30

Brutta risposta C (srotolata per un solo stack frame per potenza di 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);
}

3
tutto bene, ma perché "void main ()"? le cattive abitudini raramente vanno? : P
Nawaz,

30
@Nawaz: Perché questa è segretamente un'app GUI di Windows, quindi non importa. L'ho chiamato solo "principale" perché pensavo alle aragoste e ho un'ortografia terribile.
Martin

29

Stack Overflow:

#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);
} 

Questo è per uno stack da 8 MB. Ogni invocazione di funzioni sembra richiedere circa 32 byte (quindi 32 * 1000). Ma poi quando l'ho eseguito sono arrivato a 804 (quindi il 196 * 32; forse il runtime C ha altre parti nello stack che devi dedurre anche).


25

Divertimento con i puntatori a funzione (non è necessario nessuno di questi TMP nuovi):

#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;
}

Come nota a margine: ho preso il divieto contro i condizionali di estenderlo anche agli operatori logici e relazionali. Se si consente la negazione logica, la chiamata ricorsiva può essere semplificata per:

funcs[!!(limit-1)](x+1, limit-1);

mi piace il modo in cui ce l'hai con il bit shift. ma con il ripensamento della tua semplificazione, cosa fa il doppio botto? è bit per bit o logico? sono perso e google mi ha fatto girare in tondofuncs[!!(limit-1)](x+1, limit-1);
jon_darkstar il

Preferirei avere un singolo !e cambiare gli elementi dell'array del puntatore a funzione, ma non so se funzionerà bene con l'altra tua follia.
Chris Lutz, il

@ Chris: Sono completamente d'accordo - ma non ho preso in considerazione l'uso degli operatori logici / di relazione fino a dopo la pubblicazione e ho pensato che una patch a linea singola sarebbe stata più appropriata. Inoltre, si adatta un po 'meglio all'intera sensazione offuscata del problema.
Michael Burr,

24

Sento che questa risposta sarà molto semplice e facile da capire.

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;        
}

3
La tua risposta utilizza dichiarazioni condizionali, che sono vietate in base alla domanda.
Stevelove

4
Le dichiarazioni condizionali sono se altro ecc. Ho appena usato un'operazione logica !! Hpe è chiaro!
Pappu,

2
Anche nei tuoi commenti hai scritto "Se sì, chiama la funzione ricorsiva per stampare". Un condizionale scritto in modo non visibile è ancora un condizionale. Il numero predefinito è anche un condizionale.
Gerry,

23

Mi sono perso tutto il divertimento, tutte le buone risposte in C ++ sono già state pubblicate!

Questa è la cosa più strana che potrei inventare, non scommetterei che sia legale C99: p

#include <stdio.h>

int i = 1;
int main(int argc, char *argv[printf("%d\n", i++)])
{
  return (i <= 1000) && main(argc, argv);
}

Un altro, con un po 'di barare:

#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, ~));
}

Ultima idea, stesso trucco:

#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;
}

La chiamata mainprovoca comportamenti indefiniti, come ricordo.
Yakov Galka,

4
È perfettamente legale C. @ybungalobill: devi pensare al C ++, dove è vietato chiamare main ().
Michael Foukarakis,

@Michael: Forse non ho molta familiarità con C.
Yakov Galka il

Penso che l'utilizzo di Boost implichi C ++. Indipendentemente da ciò, complimenti per la soluzione Boost.PP.
Me22

6
Gli operatori logici &&e ||probabilmente rientrerebbero in "condizionali" poiché cortocircuitano (come farebbe ?:).
munifico

22

Facile come una torta:

int main(int argc, char* argv[])
{
    printf(argv[0]);
}

metodo di esecuzione:

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"

La specifica non dice che la sequenza deve essere generata all'interno del codice :)


18
#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];
}

15
#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;
}

15

Altro abuso di preprocessore:

#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;
}

Mi sento così sporco; Penso che ora vado a farmi una doccia.


2
Puoi chiamare A2()senza un argomento del genere?
Chris Lutz,

Ne ero curioso io stesso. Funziona correttamente con GCC, ma non so se si tratta di un comportamento ben definito.
keithmo,

Ben definito in C99, non ricordare ciò che ha detto C89, causa problemi con almeno alcune versioni di MSVC se la memoria serve.
zwol,

15

Se le soluzioni POSIX sono accettate:

#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;
}

13

Dal momento che non ci sono restrizioni sui bug ..

int i=1; int main() { int j=i/(i-1001); printf("%d\n", i++); main(); }

O meglio (?),

#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();
}

2
Dovresti quindi evitare le ottimizzazioni del compilatore, per mantenere j altrimenti inutilizzato.
bandi

2
Deve solo aggiungere volatilealla dichiarazione dij
Patrick Schlüter il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.