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 ++?


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

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

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.


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

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. ]


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


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! :)


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!


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

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

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

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

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

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

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.


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.


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

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

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

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

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).


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

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

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

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 :)


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

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.


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

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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.