Impression de 1 à 1000 sans boucle ni conditions

323

Tâche : imprimer des nombres de 1 à 1 000 sans utiliser de boucle ni d'instructions conditionnelles. Ne vous contentez pas d'écrire la déclaration printf()ou cout1000 fois.

Comment feriez-vous cela en utilisant C ou C ++?

inconnu
la source
137
La réponse évidente est d'utiliser 500 appels printfet d'imprimer deux numéros à chaque fois, non?
James McNellis
433
printf ("nombres de 1 à 1000");
jondavidjohn
7
:?n'est pas une déclaration conditionnelle (c'est une expression) ...
Chris Lutz
127
L'entrevue votre chance de briller. Dites-leur "Sans boucles ni conditionnels? Un jeu d'enfant. Je peux le faire sans ordinateur!" Retirez ensuite le stylo et le bloc-notes. Ils peuvent vous donner un aspect confus, mais expliquez simplement que si vous ne pouvez pas compter sur des constructions de langage intégrées, vous ne pouvez vraiment rien supposer.
JohnFx
8
Personnellement, je pense qu'il y avait plusieurs réponses qui avaient des solutions intelligentes et intéressantes. Je pense également que bien que cela puisse facilement être une horrible question d'entrevue, elle pourrait avoir une bonne valeur, tant que l'intervieweur ne recherche pas tant une solution complètement bien formée que la question de savoir si la personne interrogée a envisagé des approches qui indiquent une connaissance de TMP ou l'utilisation de constructions de manière inhabituelle. Je pense que ce serait mauvais si cela était utilisé comme une pure question «avoir raison / faux», mais s'il était utilisé comme point de départ d'une discussion, je pourrais voir beaucoup de valeur.
Michael Burr

Réponses:

785

Compiler la récursion du temps! : 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);
}
Prasoon Saurav
la source
8
Quelqu'un peut-il m'expliquer comment cela fonctionne? assez impressionnant.
Gath
28
@Zack: Soyons réalistes, nous imprimons 1 000 lignes à partir d'un programme écrit pour éviter délibérément les boucles. La performance n'est pas un problème.
dreamlax
42
Pour ceux qui sont assez curieux de le compiler: dans g ++, définissez -ftemplate-depth-1000. Le maximum de récursivité du modèle par défaut est 500.
Tom
6
Cela utilise toujours des conditions: la correspondance de motifs est un si glorifié.
David K.
10
@dreamlax: Ce n'est qu'une des choses que j'ai apprises au fil des ans: utilisez à '\n'moins que vous ne vouliez vraiment vider, utilisez à ++imoins que vous n'ayez réellement besoin de l'ancienne valeur de i, passez par constréférence à moins d'avoir une bonne raison de ne pas ... Lorsque les développeurs cessent d'y penser (ou ne commencent même jamais), ils se heurteront tôt ou tard à un problème où cela est important, mais ils ne savaient même pas qu'il y a des endroits où cela pourrait avoir de l'importance.
sbi
1195

Celui-ci compile en fait un assemblage qui n'a pas de conditions:

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

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


Edit: Ajout de '&' pour qu'il considère l'adresse, évitant ainsi les erreurs de pointeur.

Cette version de ce qui précède en C standard, car elle ne repose pas sur l'arithmétique sur les pointeurs de fonction:

#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);
}
Bill
la source
17
Eh bien, le code dans cette réponse n'est évidemment ni C ni C ++, donc c'est bien seulement si nous supprimons l'exigence. Ensuite, toute réponse peut être qualifiée car un compilateur hypothétique pourrait simplement produire le programme requis à partir de n'importe quelle entrée.
eq-
321
@PP, c'est assez long à expliquer, mais au fond, jc'est d'abord 1parce que c'est en fait argc, c'est-à-dire 1si le programme est appelé sans arguments. Ensuite, j/1000c'est 0jusqu'à ce que jdevienne 1000, après quoi c'est 1. (exit - main)est bien sûr la différence entre les adresses de exit()et main(). Cela signifie (main + (exit - main)*(j/1000))est main()que jdevient 1000, après quoi il devient exit(). Le résultat final est celui qui main()est appelé lorsque le programme démarre, puis s'appelle récursivement 999 fois en incrémentant j, puis appelle exit(). Ouf :)
Frédéric Hamidi
7
C'est l'un des abus les plus étonnants de CI jamais vus. Mais cela fonctionnera-t-il sur toutes les plateformes?
Qwertie
13
@Mark: il s'agit d'une signature non standard de main, vous n'êtes pas autorisé à appeler main de manière récursive, et le résultat de la soustraction des pointeurs de fonction n'est pas défini.
Yakov Galka
9
Ouais, ouais, ce n'est pas du code C ++ strictement légal pour les raisons que @ybungalobill donne, mais je dois +1 pour la pure folie et le fait qu'il compile et fonctionne sur quelques plates-formes. Il y a des moments où la réponse correcte à "Mais ce n'est pas standard!" est "Qui s'en soucie!" :)
j_random_hacker
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; }

Je suis surpris que personne ne semble avoir posté cela - je pensais que c'était le moyen le plus évident. 1000 = 5*5*5*8.

Darius Bacon
la source
Les gens l'ont posté. Les autres versions transmettent le nombre à imprimer au lieu d'utiliser un global, mais c'est essentiellement la même solution.
Chris Lutz
1
@Chris, ils utilisent la même logique exprimée dans les macros ou les modèles, faisant exploser la taille du code, non? Vous pourriez aussi bien générer la chaîne de sortie elle-même au lieu de mille printfs.
Darius Bacon
Oh ouais, je vois que la réponse de Keith génère la chaîne entière, cool. :) J'ai manqué ça.
Darius Bacon
43
Eh bien, un bel effort, mais plutôt étrange que vous n'ayez pas décomposé 8 en 2 * 2 * 2 et que vous ayez donc utilisé la factorisation de facteurs premiers unique
David Heffernan
298

On dirait qu'il n'a pas besoin d'utiliser de boucles

printf("1 10 11 100 101 110 111 1000\n");
Johannes Schaub - litb
la source
1
on pourrait dire que l'utilisation copyest de la triche
John Dibling
13
@Johannes en fait, je suis presque sûr d' printfavoir une boucle: p
icecrime
1
@litb: Notez que je n'ai pas dit que "utiliser, copy c'est tricher"
John Dibling
2
@John: copier c'est tricher. en doutez-vous? : P
Nawaz
1
sur une échelle de 1 à 10, quelle est la chance que j'utilise le binaire?
Jordan
270

Voici trois solutions que je connais. La seconde pourrait être discutée cependant.

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

[ Modifier: (1) et (4) peuvent être utilisés uniquement pour la compilation des constantes de temps, (2) et (3) peuvent également être utilisés pour les expressions d'exécution - terminer la modification. ]

ybungalobill
la source
5
De plus, je dirais qu'un court-circuit n'est pas un conditionnel ... Pas une déclaration, c'est vrai, mais une expression conditionnelle, je dirais. À condition de définir une expression conditionnelle comme "quelque chose qui génère des sauts conditionnels dans l'assembleur".
Kos
5
Question qui m'a frappé lors de la lecture du constructeur: la norme exige-t-elle que chaque élément du tableau soit construit en séquence? Il importerait que le constructeur ait des effets secondaires. Je suis sûr que chaque compilateur sensé l'implémente comme une boucle 0-> 1000, mais je me demande si vous pourriez toujours être conforme et faire une boucle en arrière ...
Joseph Garvin
6
@Joseph - Le constructeur ne devrait pas être affecté par l'ordre dans lequel les objets individuels sont lancés, mais c'est une bonne question.
Chris Lutz
12
@Joseph ceci est défini par 12.6 / 3 (C ++ 03). L'initialisation se fait par ordre d'abonnement.
Johannes Schaub - litb
2
@Joseph: Et ils sont également détruits dans l'ordre inverse, vous pouvez donc utiliser un destructeur tout aussi facilement :)
j_random_hacker
263

Je n'écris pas la déclaration printf 1000 fois!

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

Vous êtes les bienvenus ;)

Martin Thurau
la source
223
J'espère que vous avez écrit un programme pour générer cette ligne.
Martin York
32
open ("1000.c", 'w'). write ('printf ("% s");'% ("\ n" .join ([str (x) pour x dans xrange (1,1000)]) ))
Tyler Eaves
53
J'espère que le programme que vous avez écrit pour générer cette ligne ne contient pas de boucle!
Jeeyoung Kim
20
Une macro Vim ferait le travail rapidement.
StackedCrooked
2
Un peu de Perl le génère de manière fantaisiste:$r='printf("'; for (1..1000) { $r.="$_\\n" } $r.='");'; print $r;
sidyll
213
printf("%d\n", 2);
printf("%d\n", 3);

Il n'imprime pas tous les nombres, mais il "Imprime les nombres de 1 à 1000". Question ambiguë pour la victoire! :)

Matthew Flaschen
la source
77
mon préféré après 'printf ("nombres de 1 à 1000")' - les questions idiotes nécessitent des réponses idiotes.
SEngstrom
C'est génial. +1 pour avoir profité de l'ambiguïté de la question. haha
Nawaz
2
Édité; en aucune manière, la forme ou la forme a ce code print "Print numbers from 1 to 1000."- question ambiguë pour la victoire, les descriptions inexactes sucent :)
sehe
Wow, il y a eu un peu de vandalisme sur les réponses à cette question ces derniers temps. Quelque chose me dit que nous devrions mettre à niveau ce verrou vers un verrou historique.
BoltClock
172

Déclenchez une erreur fatale! Voici le fichier, 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);
}

Compilez, puis exécutez à l'invite du shell:

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

Cela imprime en effet les nombres de 1 à 1000, sans boucles ni conditions!

Aaron Maxwell
la source
43
vous devez appeler fflush (stdout); après chaque printf () ... Lorsqu'un programme plante, il n'est pas garanti que le tampon de sortie sera imprimé à l'écran.
zakk
10
@zakk: Ce n'est pas strictement nécessaire - par défaut, stdout est mis en mémoire tampon, donc le \nsera suffisant pour vider la sortie.
psmears
24
stdout est mis en mémoire tampon de ligne s'il peut être déterminé qu'il s'agit d'un périphérique interactif , sinon il est entièrement mis en mémoire tampon. Si le professeur redirige stdout vers un fichier pour une vérification automatique, vous
échouerez
danger de débordement de pile (par exemple dans un environnement intégré)
Hernán Eche
166

Utilisation des commandes système:

system("/usr/bin/seq 1000");
marcog
la source
15
High chance /usr/bin/sequtilise une boucle en interne. :)
@jokester: vous voulez dire, parce que Solaris / BSD n'a pas d' sequtilitaire (dans la configuration par défaut)? <sourire />
sehe
Je déteste dire cela (enfin, non, je ne le fais pas), mais il y a un bug dans votre solution. Il n'imprime pas le bon ensemble de chiffres. :) Voici le correctif: system("/bin/echo {1..1000}"); Si seulement vous aviez d'abord écrit le test unitaire ...
Don Branson
1
Un mec brillant a décidé de changer ma réponse, ce n'est donc pas mon erreur.
moinudin
100

Non testé, mais devrait être le standard C vanille:

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);
}
munificence
la source
29
@Prasoon: C'est une relation.
Yakov Galka
28
l'exigence est "pas de conditions" (si, interrupteur, etc.). pas "sans conditions"
jon_darkstar
32
<n'est pas une condition. C'est un opérateur relationnel. if/ elseest une instruction conditionnelle. ?:est un opérateur conditionnel. <est juste un opérateur qui retourne une valeur booléenne. Il s'agit probablement d'une seule instruction machine sans saut ni quoi que ce soit.
Chris Lutz
12
Lutz @ Chris: Sur x86, il est 3: instructions cmpl, setleet movzbl. x86-64 est cela plus un cltq. PowerPC est 2 instructions: cmpwiet crnot.
Adam Rosenfield
4
1 - i / 1000. Aucune comparaison!
Thai
96

Un peu ennuyeux par rapport aux autres ici, mais probablement ce qu'ils recherchent.

#include <stdio.h>

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

void main(void) {
    f(1000);
}
Aaron
la source
Le rend plus court. définir i = 1 en dehors de main puis à l'intérieur de main: printf ("% d \ n", 11 - i) && --i && main (i);
jftuga
3
@Jens Schauder: En profitant de l' &&évaluation paresseuse dans la première ligne de f().
Rafał Dowgird
10
Ce n'est pas ennuyeux, c'est simple. Si vous pouvez faire la même chose avec une fonction courte que vous pouvez avec un énorme gâchis de magie de modèle, alors vous devriez le faire avec la fonction :)
amertune
21
Le && est un conditionnel. Un ET mathématique évaluera les deux côtés (comme le font Java et Ada "ET"). && n'évaluera le 2e opérateur que si (le voici) le premier est vrai. Ou autre exemple: dans Ada, l'opérateur de court-circuit est appelé "OU ALORS" - en utilisant ALORS pour indiquer l'aspect conditionnel. Désolé, vous auriez pu tout aussi bien utiliser le? : opérateur.
Martin
Pas besoin de s'excuser. && est un opérateur de comparaison. L'opérateur ternaire est un conditionnel.
Aaron
71

La tâche n'a jamais spécifié que le programme doit se terminer après 1000.

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

int main(){
   f(1);
}

( Peut être raccourci à ceci si vous exécutez ./a.out sans paramètres supplémentaires )

void main(int n) {
   printf("%d\n", n);
   main(n+1);
}
Brian
la source
Mais cela ne s'arrête pas à 1000. Ça continue.
Remy Lebeau
Peut être raccourci uniquement si vous supprimez l'exigence de C ou C ++. Ensuite, tout "programme" fera l'affaire, car un compilateur théorique pourrait générer le programme que vous voulez (à partir de n'importe quelle entrée).
eq-
@eq Encore une fois, cela se compile et fonctionne très bien…
Mark McDonald
72
Après coup: nous pouvons même échapper aux mathématiques apparentes . Si nous employons rand(), nous imprimerons tous les nombres de 1 à 1000. Finalement =: P
5
@pooh: Pas nécessairement, car rand () a une chance de se répéter après une certaine séquence, et cette séquence pourrait ne pas tomber dans la solution définie pour ce problème
dchhetri
71

C'est de la tarte! : P

#include <iostream>

static int current = 1;

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

int main()
{
    print numbers [1000];
}
Zelix
la source
vous voudrez peut-être faire "static int current = 0" sinon vous imprimerez de 2 à 1001.
Shinnok
j'ai changé ++ actuel en courant ++
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);
}
MangleSky
la source
3
Ummmm. Macros. C'est quoi pour le dîner.
EvilTeach
42

Nous pouvons lancer 1000 threads, chacun imprimant l'un des numéros. Installez OpenMPI , compilez en utilisant mpicxx -o 1000 1000.cppet exécutez en utilisant mpirun -np 1000 ./1000. Vous devrez probablement augmenter votre limite de descripteurs à l'aide de limitou ulimit. Notez que cela sera plutôt lent, à moins que vous n'ayez beaucoup de cœurs!

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

Bien sûr, les numéros ne seront pas nécessairement imprimés dans l'ordre, mais la question ne nécessite pas qu'ils soient commandés.

moinudin
la source
1
Boucle implicite dans la bibliothèque? Mais +1 quand même pour une nouvelle approche.
Chris Lutz
11
@Chris La plupart des solutions n'ont-elles pas une boucle cachée quelque part?
moinudin
Je suppose que si vous prenez l'approche "boucles dans le compilateur". Puisque (en dehors d'une boucle possible sur les arguments dans MPI::Init()) je ne peux pas imaginer de boucles dans le binaire réel de votre programme 1000.cpp, je vous ai donné un +1, même s'il y a certainement des boucles en cours d'exécution lorsque vous l'exécutez.
Chris Lutz
40

Avec C simple:

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

Bien sûr, vous pouvez implémenter la même idée pour d'autres bases (2: print2 print4 print8 ...) mais le nombre 1000 ici suggère la base 10. Vous pouvez également réduire un peu le nombre de lignes en ajoutant des fonctions intermédiaires: print2() print10() print20() print100() print200() print1000()et d'autres alternatives équivalentes.

leonbloy
la source
Pourquoi le nombre 1000 suggère-t-il la base 10? Dans toute notation positionnelle avec base B, 1000 est un nombre parfaitement valide et toujours égal B^3.
Philip
Je voulais juste dire que, étant donné la façon dont le nombre est représenté dans la base 10, la factorisation "10x10x10" s'est suggérée, mais que d'autres alternatives sont possibles. Je suppose que j'aurais dû dire "factorisation" au lieu de "base"
leonbloy
34

Utilisez simplement std :: copy () avec un itérateur spécial.

#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, " "));
}
Loki Astari
la source
Je pense que votre code commence à 0. Je suis également d'accord avec Chris, la question telle que je l'ai vue il y a des années a été déclarée "sans aucune bibliothèque sauf pour IO". encore +1 :)
Yakov Galka
3
@Chris Lutz: L'implémentation de la copie n'est pas définie. Je peux même utiliser le code du modèle comme ci-dessus (vous ne le savez pas; je ne sais pas). Vous ne pouvez donc pas dire qu'il utilise une boucle parce que nous ne savons pas.
Martin York
7
En fait, mon choix médiocre ne serait pas autant la boucle implicite std::copyque le conditionnel implicite dans le operator !=(). Quoi qu'il en soit, c'est une approche intelligente du traitement d'une plage, et des approches intelligentes sont ce que je recherche en réponse à des questions comme celle-ci.
Michael Burr
l'implémentation spécifique n'est pas définie
selvaiyyamperumal
@selvaiyyamperumal: Je ne sais pas exactement de quoi vous parlez. Mais si vous parlez de comportement, la norme n'est pas d'accord avec vous. «Comportement défini par l'implémentation» signifie qu'il est bien défini mais doit être explicitement documenté par l'implémentation. "Comportement indéfini" signifie que tout peut arriver.
Martin York
33

Utilisation du pointeur de fonction (ab). Pas de magie de préprocesseur pour augmenter la sortie. 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();
}
Filipe Z
la source
3
Voilà à quoi je pensais. Une personne précédente a dit que 5 * 5 * 5 * 8 = 1000. Je pensais que c'était drôle qu'il lui manquait les 10 ^ 3 évidents. Bonne solution!
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); }
Dustin
la source
30

Réponse Ugly C (déroulée pour une seule trame de pile par puissance de 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);
}
Martin
la source
3
tout va bien, mais pourquoi "void main ()"? les mauvaises habitudes disparaissent rarement? : P
Nawaz
30
@Nawaz: Parce que c'est secrètement une application Windows GUI, donc cela n'a pas d'importance. Je l'ai seulement appelé "principal" parce que je pensais aux homards et à l'orthographe terrible.
Martin
29

Débordement de pile:

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

C'est pour une pile de 8 Mo. Chaque appel de fonction semble prendre environ 32 octets (d'où le 32 * 1000). Mais ensuite, lorsque je l'ai exécuté, je n'ai atteint que 804 (d'où le 196 * 32; peut-être que le runtime C a d'autres parties de la pile que vous devez également déduire).

utilisateur560766
la source
25

Amusant avec les pointeurs de fonction (rien de tout cela TMP nouveau-né nécessaire):

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

En remarque: j'ai pris l'interdiction des conditionnels pour s'étendre également aux opérateurs logiques et relationnels. Si vous autorisez la négation logique, l'appel récursif peut être simplifié pour:

funcs[!!(limit-1)](x+1, limit-1);
Michael Burr
la source
j'aime la façon dont vous l'avez avec le décalage de bits. mais avec votre simplification après coup, que fait le double coup? son au niveau du bit ou logique? im perdu et google m'a fait tourner en rondfuncs[!!(limit-1)](x+1, limit-1);
jon_darkstar
Je préfère en avoir un seul !et changer les éléments du tableau de pointeurs de fonction, mais je ne sais pas si cela fonctionnera bien avec votre autre folie.
Chris Lutz
@Chris: Je suis entièrement d'accord - mais je n'ai envisagé d'utiliser des opérateurs logiques / relationnels qu'après la publication, et je me suis dit qu'un patch sur une seule ligne serait plus approprié. En outre, il s'intègre un peu mieux à l'ensemble de la sensation obscurcie du problème.
Michael Burr
24

Je pense que cette réponse sera très simple et facile à comprendre.

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;        
}
Pappu
la source
3
Votre réponse utilise des instructions conditionnelles, qui sont interdites selon la question.
stevelove
4
les instructions conditionnelles sont sinon, etc. Je viens d'utiliser une opération logique !! Hpe c'est clair!
Pappu
2
Même dans vos commentaires, vous avez écrit "Si oui, appelez la fonction récursive pour imprimer". Un conditionnel écrit d'une manière non évidente est toujours un conditionnel. La valeur par défaut num est également conditionnelle.
Gerry
23

J'ai raté tout le plaisir, toutes les bonnes réponses C ++ ont déjà été postées!

C'est la chose la plus étrange que j'ai pu trouver, je ne parierais pas que c'est légal C99 cependant: p

#include <stdio.h>

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

Un autre, avec un peu de triche:

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

Dernière idée, même triche:

#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;
}
glace
la source
L'appel mainentraîne un comportement indéfini si je me souviens bien.
Yakov Galka
4
C'est parfaitement légal C. @ybungalobill: Vous devez penser au C ++, où l'appel à main () est spécifiquement interdit.
Michael Foukarakis
@Michael: Peut-être que je ne suis pas très familier avec C.
Yakov Galka
Je pense que l'utilisation de Boost implique C ++. Quoi qu'il en soit, bravo pour la solution Boost.PP.
me22
6
Les opérateurs logiques &&et ||seraient probablement tomber sous « conditionals » car ils court-circuit (comme le ferait ?:).
munificent
22

C'est de la tarte:

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

méthode d'exécution:

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 spécification ne dit pas que la séquence doit être générée à l' intérieur du code :)

Rodrigo
la source
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];
}
John Dibling
la source
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;
}
6502
la source
15

Plus d'abus de préprocesseur:

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

Je me sens tellement sale; Je pense que je vais prendre une douche maintenant.

Keithmo
la source
2
Pouvez-vous appeler A2()sans argument comme ça?
Chris Lutz
J'étais moi-même curieux à ce sujet. Cela fonctionne correctement avec GCC, mais je ne sais pas si c'est un comportement bien défini.
Keithmo
Bien défini dans C99, je ne me souviens pas de ce que C89 a dit, cela cause des problèmes avec au moins certaines versions de MSVC si la mémoire est bonne.
zwol
15

Si les solutions POSIX sont acceptées:

#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;
}
jweyrich
la source
13

Puisqu'il n'y a aucune restriction sur les bugs ..

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

Ou encore mieux (?),

#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();
}
Serkan
la source
2
Vous devez alors éviter les optimisations du compilateur pour conserver le j autrement inutilisé.
bandi
2
Il suffit d'ajouter volatileà la déclaration dej
Patrick Schlüter