Impresión de 1 a 1000 sin bucle o condicionales

323

Tarea : Imprima números del 1 al 1000 sin usar ningún bucle o declaraciones condicionales. No solo escriba la declaración printf()o cout1000 veces.

¿Cómo harías eso usando C o C ++?

desconocido
fuente
137
La respuesta obvia es usar 500 llamadas printfe imprimir dos números cada vez, ¿no?
James McNellis
433
printf ("números del 1 al 1000");
jondavidjohn
77
:?no es una declaración condicional (es una expresión) ...
Chris Lutz
127
La entrevista tu oportunidad de brillar. Dígales "¿Sin bucles ni condicionales? Juego de niños. ¡Puedo hacerlo sin una computadora!" Luego saque el bolígrafo y el bloc de notas. Pueden darle una mirada confusa, pero solo explique que si no puede contar con construcciones de lenguaje incorporadas, realmente no puede asumir nada.
JohnFx
8
Personalmente, creo que hubo varias respuestas que tuvieron soluciones inteligentes e interesantes. También creo que si bien esta podría ser una pregunta de entrevista horrible, podría tener un buen valor, siempre y cuando el entrevistador realmente no busque tanto una solución completamente bien formada como si el entrevistado consideró enfoques que indiquen conocimiento de TMP o el uso de construcciones de formas inusuales. Creo que sería malo si esto se usara como una pregunta pura de "acierto / error", pero si se usara como el punto de partida de una discusión, podría ver mucho valor.
Michael Burr

Respuestas:

785

Tiempo de compilación recursividad! :PAGS

#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
fuente
8
¿Alguien puede explicarme cómo funciona esto? muy impresionante.
Gath
28
@Zack: Seamos realistas, estamos imprimiendo 1,000 líneas de un programa escrito para evitar bucles deliberadamente. El rendimiento no es un problema.
dreamlax
42
Para aquellos lo suficientemente curiosos como para compilar esto: en g ++, establezca -ftemplate-depth-1000. La recursividad máxima de plantilla predeterminada es 500.
Tom
66
Esto todavía utiliza condicionales: la coincidencia de patrones es un glorificado if.
David K.
10
@dreamlax: Es solo una de esas cosas que he aprendido de la experiencia a lo largo de los años: use a '\n'menos que realmente quiera enjuagar, use a ++imenos que realmente necesite el valor anterior i, pase por constreferencia a menos que tenga una buena razón para no ... Cuando los desarrolladores dejan de pensar en estos (o nunca comienzan), tarde o temprano se encontrarán con un problema donde esto importa, solo que ni siquiera sabían que hay puntos en los que podría importar.
sbi
1195

Este realmente se compila en un ensamblaje que no tiene condicionales:

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

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


Editar: se agregó '&' para que considere la dirección y, por lo tanto, evada los errores de puntero.

Esta versión de lo anterior en el estándar C, ya que no depende de la aritmética en los punteros de función:

#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
fuente
17
Bueno, el código en esta respuesta obviamente no es ni C ni C ++, por lo que está bien solo si eliminamos el requisito. Entonces cualquier respuesta puede calificar porque un compilador hipotético podría producir el programa requerido desde cualquier entrada.
eq-
321
@PP, eso es bastante largo de explicar, pero básicamente jes inicialmente 1porque en realidad argces así, 1si el programa se llama sin argumentos. Entonces, j/1000es 0hasta que se jconvierte 1000, después de lo cual es 1. (exit - main)es, por supuesto, la diferencia entre las direcciones de exit()y main(). Eso significa que (main + (exit - main)*(j/1000))es main()hasta que se jconvierte 1000, después de lo cual se convierte exit(). El resultado final es que main()se llama cuando se inicia el programa, luego se llama recursivamente 999 veces mientras se incrementa j, luego se llama exit(). Whew :)
Frédéric Hamidi
77
Este es uno de los abusos más sorprendentes de CI que he visto. ¿Pero funcionará en todas las plataformas?
Qwertie
13
@ Mark: esta no es la firma estándar de main, no se le permite llamar a main de forma recursiva y el resultado de restar los punteros de función no está definido.
Yakov Galka
99
Sí, sí, no es un código C ++ estrictamente legal por las razones que explica @ybungalobill, pero tengo que hacer +1 por pura locura y el hecho de que compila y funciona en algunas plataformas. Hay momentos en que la respuesta correcta a "¡Pero no es estándar!" es "¡A quién le importa!" :)
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; }

Me sorprende que nadie haya publicado esto, pensé que era la forma más obvia. 1000 = 5*5*5*8.

Darius Bacon
fuente
La gente ha publicado esto. Las otras versiones pasan el número para imprimir en lugar de usar un global, pero es esencialmente la misma solución.
Chris Lutz
1
@ Chris, usan la misma lógica expresada en macros o plantillas, explotando el tamaño del código, ¿verdad? También podría generar la cadena de salida en lugar de mil printfs.
Darius Bacon
Oh sí, veo que la respuesta de Keith genera toda la cadena, genial. :) Me lo perdí.
Darius Bacon
43
Bueno, buen esfuerzo, pero bastante extraño que no descompongas 8 en 2 * 2 * 2 y, por lo tanto, utilices la factorización prima única
David Heffernan
298

Parece que no necesita usar bucles

printf("1 10 11 100 101 110 111 1000\n");
revs Johannes Schaub - litb
fuente
1
se podría argumentar que usar copyes hacer trampa
John Dibling
13
@Johannes en realidad estoy bastante seguro de que printftiene un bucle: p
icecrime
1
@litb: Tenga en cuenta que no dije que "usar copy es hacer trampa"
John Dibling
2
@John: copiar es hacer trampa. lo dudas? : P
Nawaz
1
en una escala del 1 al 10, ¿cuál es la posibilidad de que esté usando binario?
Jordan
270

Aquí hay tres soluciones que sé. Sin embargo, el segundo podría ser discutido.

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

[ Editar: (1) y (4) se pueden usar solo para compilar constantes de tiempo, (2) y (3) también se pueden usar para expresiones de tiempo de ejecución - finalice la edición. ]

ybungalobill
fuente
55
Además, diría que un cortocircuito no es condicional ... No es una declaración, es cierto, sino una expresión condicional, diría. Siempre que definamos una expresión condicional como "algo que produce saltos condicionales en ensamblador".
Kos
55
Pregunta que me golpeó al leer el constructor: ¿El estándar exige que cada elemento de la matriz se construya en secuencia? Importaría si el constructor tuviera efectos secundarios. Estoy seguro de que cada compilador cuerdo lo implementa como un ciclo 0-> 1000, pero me pregunto si aún podría cumplir y hacer un ciclo hacia atrás ...
Joseph Garvin
66
@Joseph: el constructor no debería verse afectado por el orden en que se inician los objetos individuales, pero es una buena pregunta.
Chris Lutz
12
@Joseph, esto se define en 12.6 / 3 (C ++ 03). La inicialización se realiza en orden de suscripción.
Johannes Schaub - litb
2
@Joseph: Y también se destruyen en orden inverso, por lo que podría usar un destructor con la misma facilidad :)
j_random_hacker
263

¡No estoy escribiendo la declaración printf 1000 veces!

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

De nada ;)

Martin Thurau
fuente
223
Espero que hayas escrito un programa para generar esa línea.
Martin York
32
open ("1000.c", 'w'). write ('printf ("% s");'% ("\ n" .join ([str (x) para x en xrange (1,1000)]) ))
Tyler Eaves
53
¡Espero que el programa que escribiste para generar esa línea no contenga loop!
Jeeyoung Kim
20
Una macro Vim haría el trabajo rápidamente.
StackedCrooked
2
Un poco de Perl genera en una forma elegante:$r='printf("'; for (1..1000) { $r.="$_\\n" } $r.='");'; print $r;
sidyll
213
printf("%d\n", 2);
printf("%d\n", 3);

No imprime todos los números, pero sí "Imprime números del 1 al 1000". ¡Pregunta ambigua para la victoria! :)

Matthew Flaschen
fuente
77
mi favorito después de 'printf ("números del 1 al 1000") - las preguntas tontas requieren respuestas tontas.
SEngstrom
Esto es asombroso. +1 por aprovechar la ambigüedad en la pregunta. jaja
Nawaz
2
Editado; de ninguna manera, o forma, este código print "Print numbers from 1 to 1000."- pregunta ambigua para la victoria, descripciones inexactas apestan :)
sehe
Wow, últimamente ha habido un poco de vandalismo en las respuestas de esta pregunta. Algo me dice que deberíamos actualizar ese bloqueo a un bloqueo histórico.
BoltClock
172

¡Activa un error fatal! Aquí está el archivo, 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);
}

Compile, luego ejecute en un indicador de shell:

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

¡De hecho, esto imprime los números del 1 al 1000, sin ningún bucle o condicionales!

Aaron Maxwell
fuente
43
debe llamar a fflush (stdout); después de cada printf () ... Cuando un programa falla, no se garantiza que el búfer de salida se imprima en la pantalla.
zakk
10
@zakk: Eso no es estrictamente necesario: de forma predeterminada, stdout tiene un buffer de línea, por lo \nque será suficiente para vaciar la salida.
Salidas del
24
stdout tiene un buffer de línea si se puede determinar que es un dispositivo interactivo , de lo contrario, está completamente protegido. Si el profesor redirige stdout a un archivo para verificación automática,
fallarás
peligro de desbordamiento de pila (por ejemplo, en un entorno incrustado)
Hernán Eche
166

Usando comandos del sistema:

system("/usr/bin/seq 1000");
marcog
fuente
15
Alta probabilidad /usr/bin/sequtiliza un bucle internamente. :)
@jokester: ¿quiere decir que Solaris / BSD no tiene una sequtilidad (en la configuración predeterminada)? <sonrisa />
sehe
Odio decir esto (bueno, no, no lo hago), pero hay un error en su solución. No imprime el conjunto correcto de números. :) Aquí está la solución: system("/bin/echo {1..1000}"); Si solo hubieras escrito la prueba de la unidad primero ...
Don Branson
1
Un tipo brillante decidió cambiar mi respuesta, así que ese no es mi error.
Moinudin
100

No probado, pero debe ser estándar C de vainilla:

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);
}
munificente
fuente
29
@Prasoon: Es una relación.
Yakov Galka
28
el requisito es "sin condicionales" (if, switch, etc.). no "sin condiciones"
jon_darkstar
32
<No es una condición. Es un operador relacional. if/ elsees una declaración condicional. ?:Es un operador condicional. <es solo un operador que devuelve un valor booleano. Probablemente sea una sola instrucción de máquina sin saltos ni nada.
Chris Lutz
12
@ Chris Lutz: En x 86, que es 3: instrucciones cmpl, setley movzbl. x86-64 es eso más a cltq. PowerPC es 2 instrucciones: cmpwiy crnot.
Adam Rosenfield
44
1 - i / 1000. No hay comparaciones!
Tailandés
96

Un poco aburrido en comparación con otros aquí, pero probablemente lo que están buscando.

#include <stdio.h>

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

void main(void) {
    f(1000);
}
Aaron
fuente
Lo hizo más corto. establecer i = 1 fuera de main y luego dentro de main: printf ("% d \ n", 11 - i) && --i && main (i);
jftuga
3
@Jens Schauder: Al aprovechar la &&evaluación perezosa en la primera línea de f().
Rafał Dowgird
10
Esto no es aburrido, es simple. Si puede hacer lo mismo con una función corta como puede hacerlo con un enorme desorden de plantilla mágica, entonces debe hacerlo con la función :)
amertune
21
El && es condicional. Un AND matemático evaluará ambos lados (como lo hace Java & y Ada "AND") && evaluará el segundo operador solo si (aquí está) el primero es verdadero. O otro ejemplo: en Ada, el operador de cortocircuitos se llama "O ENTONCES", usando ENTONCES para indicar el aspecto condicional. Lo siento, ¿podrías haber usado el? : operador.
Martin
No necesitas disculparte. && es un operador de comparación. El operador ternario es condicional.
Aaron
71

La tarea nunca especificó que el programa debe terminar después de 1000.

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

int main(){
   f(1);
}

( Se puede acortar a esto si ejecuta ./a.out sin parámetros adicionales )

void main(int n) {
   printf("%d\n", n);
   main(n+1);
}
Brian
fuente
Sin embargo, no se detiene en 1000. Simplemente sigue adelante.
Remy Lebeau
Solo se puede acortar si elimina el requisito de C o C ++. Entonces cualquier "programa" funcionará, porque un compilador teórico podría generar el programa que desea (desde cualquier entrada).
eq-
@eq Nuevamente, esto se compila y funciona bien ...
Mark McDonald
72
Como una ocurrencia tardía: incluso podemos evadir las matemáticas aparentes . Si empleamos rand(), imprimiremos todos los números del 1 al 1000. Eventualmente =: P
55
@pooh: No necesariamente, ya que rand () tiene la posibilidad de repetirse después de cierta secuencia, y esa secuencia podría no estar en la solución establecida para este problema
dchhetri
71

¡Muy fácil! :PAGS

#include <iostream>

static int current = 1;

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

int main()
{
    print numbers [1000];
}
revs Zelix
fuente
es posible que desee hacer "static int current = 0", de lo contrario se imprimirá de 2 a 1001.
Shinnok
Cambié ++ actual a actual ++
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
fuente
3
Ummmm Macros Es lo que hay para cenar.
EvilTeach
42

Podemos lanzar 1000 hilos, cada uno imprimiendo uno de los números. Instale OpenMPI , compile usando mpicxx -o 1000 1000.cppy ejecute usando mpirun -np 1000 ./1000. Probablemente necesitará aumentar su límite de descriptor usando limito ulimit. Tenga en cuenta que esto será bastante lento, ¡a menos que tenga muchos núcleos!

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

Por supuesto, los números no se imprimirán necesariamente en orden, pero la pregunta no requiere que se ordenen.

moinudin
fuente
1
¿Bucle implícito en la biblioteca? Pero de todos modos +1 para un nuevo enfoque.
Chris Lutz
11
@Chris ¿La mayoría de las soluciones no tienen un bucle oculto en alguna parte?
moinudin
Supongo que si tomas el enfoque de "bucles en el compilador". Dado que (fuera de un posible bucle sobre los argumentos en MPI::Init()) no puedo imaginar ningún bucle en el binario real de su programa 1000.cpp, le di un +1, aunque ciertamente hay bucles en ejecución cuando lo ejecuta.
Chris Lutz
40

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

Por supuesto, puede implementar la misma idea para otras bases (2: print2 print4 print8 ...) pero el número 1000 aquí sugiere la base 10. También puede reducir un poco el número de líneas que agregan funciones intermedias: print2() print10() print20() print100() print200() print1000()y otras alternativas equivalentes.

leonbloy
fuente
¿Por qué el número 1000 sugiere la base 10? En cualquier notación posicional con base B, 1000 es un número perfectamente válido y siempre es igual B^3.
Philip
Simplemente quise decir que, dada la forma en que se representa el número en la base 10, la factorización "10x10x10" se sugirió, pero que otras alternativas son posibles. Creo que debería haber dicho "factorización" en lugar de "base"
leonbloy
34

Simplemente use std :: copy () con un iterador especial.

#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
fuente
Creo que su código comienza desde 0. También estoy de acuerdo con Chris, la pregunta como la vi hace años se declaró como "sin ninguna biblioteca, excepto IO". todavía +1 :)
Yakov Galka
3
@ Chris Lutz: La implementación de la copia no está definida. Incluso puedo usar el código de plantilla como el anterior (simplemente no lo sabes). Entonces no puedes decir que usa un bucle porque no lo sabemos.
Martin York
77
En realidad, mi selección de liendres no sería el bucle implícito std::copytanto como el condicional implícito en el operator !=(). De todos modos, es una forma inteligente de procesar un rango, y los enfoques inteligentes es lo que busco en respuesta a preguntas como esta.
Michael Burr
la implementación específica no está definida
selvaiyyamperumal
@selvaiyyamperumal: No estoy seguro exactamente de lo que estás hablando. Pero si está hablando de comportamiento, el estándar no está de acuerdo con usted. "Comportamiento definido de implementación" significa que está bien definido, pero la implementación debe documentarlo explícitamente. "Comportamiento indefinido" significa que cualquier cosa puede suceder.
Martin York
33

Uso del puntero de función (ab). Sin magia de preprocesador para aumentar la producción. 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
fuente
3
Esto es en lo que estaba pensando. Una persona anterior dijo que 5 * 5 * 5 * 8 = 1000. Pensé que era divertido que le faltara el obvio 10 ^ 3. Buena solución!
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
fuente
30

Respuesta fea de C (desenrollada para un solo cuadro de pila por potencia 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);
}
Martín
fuente
3
todo está bien, pero ¿por qué "void main ()"? los malos hábitos rara vez desaparecen? : P
Nawaz
30
@Nawaz: Debido a que esta es secretamente una aplicación GUI de Windows, no importa. Solo lo llamé "principal" porque estaba pensando en las langostas y tenía una ortografía terrible.
Martin
29

Desbordamiento de pila:

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

Esto es para una pila de 8 MB. Cada invocación de función parece tomar aproximadamente 32 bytes (de ahí el 32 * 1000). Pero luego, cuando lo ejecuté, solo llegué a 804 (de ahí el 196 * 32; quizás el tiempo de ejecución C tiene otras partes en la pila que también debes deducir).

user560766
fuente
25

Diversión con punteros de función (no se necesita nada de ese TMP novedoso):

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

Como nota al margen: tomé la prohibición de los condicionales para extenderla también a operadores lógicos y relacionales. Si permite la negación lógica, la llamada recursiva se puede simplificar para:

funcs[!!(limit-1)](x+1, limit-1);
Michael Burr
fuente
Me gusta cómo lo tienes con el cambio de bits. pero con su simplificación de último momento, ¿qué hace el doble golpe? es bitwise o lógico? estoy perdido y google me hizo dar vueltas en círculosfuncs[!!(limit-1)](x+1, limit-1);
jon_darkstar
Prefiero tener un solo !y cambiar los elementos de la matriz de puntero de función, pero no sé si eso funcionará bien con su otra locura.
Chris Lutz
@ Chris: Estoy completamente de acuerdo, pero no consideré usar operadores lógicos / de relación hasta después de la publicación, y pensé que un parche de una sola línea sería más apropiado. Además, encaja un poco mejor con toda la sensación ofuscada del problema.
Michael Burr
24

Siento que esta respuesta será muy simple y fácil de entender.

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
fuente
3
Su respuesta utiliza declaraciones condicionales, que están prohibidas de acuerdo con la pregunta.
stevelove
44
las declaraciones condicionales son, si no, etc. ¡Acabo de usar una operación lógica! Espero que esté claro!
Pappu
2
Incluso en sus comentarios escribió "En caso afirmativo, llame a la función recursiva para imprimir". Un condicional escrito de manera no obvia sigue siendo un condicional. El valor numérico predeterminado también es condicional.
Gerry
23

¡Extrañé toda la diversión, todas las buenas respuestas de C ++ ya se han publicado!

Esto es lo más extraño que se me ocurre, aunque no apostaría que es legal C99: p

#include <stdio.h>

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

Otro, con un poco de trampa:

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

Última idea, mismo truco:

#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;
}
revs de hielo
fuente
Llamar mainresulta en un comportamiento indefinido como recuerdo.
Yakov Galka
44
Es perfectamente legal C. @ybungalobill: debe estar pensando en C ++, donde llamar a main () está específicamente prohibido.
Michael Foukarakis
@Michael: Tal vez, no estoy muy familiarizado con C.
Yakov Galka
Creo que usar Boost implica C ++. En cualquier caso, felicitaciones por la solución Boost.PP.
me22
66
Los operadores lógicos &&y ||probablemente caerían en "condicionales" ya que se cortocircuitan (como lo haría ?:).
munificent
22

Muy fácil:

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

método de ejecución:

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 especificación no dice que la secuencia debe generarse dentro del código :)

Rodrigo
fuente
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
fuente
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
fuente
15

Más abuso del preprocesador:

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

Me siento tan sucia; Creo que iré a ducharme ahora.

keithmo
fuente
2
¿Puedes llamar A2()sin una discusión como esa?
Chris Lutz
Tenía curiosidad sobre eso yo mismo. Funciona correctamente con GCC, pero no sé si es un comportamiento bien definido.
keithmo
Bien definido en C99, no recuerdo lo que dijo C89, causa problemas con al menos algunas versiones de MSVC si la memoria funciona.
zwol
15

Si se aceptan soluciones 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;
}
jweyrich
fuente
13

Dado que no hay restricción en los errores ..

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

O mejor(?),

#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
fuente
2
Debe evitar las optimizaciones del compilador para mantener el j no utilizado.
bandi
2
Solo necesita agregar volatilea la declaración dej
Patrick Schlüter