J'essaie d'imprimer des nombres de 1 à 100 sans utiliser de boucles, en utilisant C #. Des indices?
La récursivité peut-être?
public static void PrintNext(i) {
if (i <= 100) {
Console.Write(i + " ");
PrintNext(i + 1);
}
}
public static void Main() {
PrintNext(1);
}
Pas de boucles, pas de condition, et pas de sortie littérale codée en dur, solution "diviser et conquérir FTW":
class P
{
static int n;
static void P1() { System.Console.WriteLine(++n); }
static void P2() { P1(); P1(); }
static void P4() { P2(); P2(); }
static void P8() { P4(); P4(); }
static void P16() { P8(); P8(); }
static void P32() { P16(); P16(); }
static void P64() { P32(); P32(); }
static void Main() { P64(); P32(); P4(); }
}
Approche alternative:
using System;
class C
{
static int n;
static void P() { Console.WriteLine(++n); }
static void X2(Action a) { a(); a(); }
static void X5(Action a) { X2(a); X2(a); a(); }
static void Main() { X2(() => X5(() => X2(() => X5(P)))); }
}
Console.Out.WriteLine('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');
Un de plus:
Console.WriteLine(
String.Join(
", ",
Array.ConvertAll<int, string>(
Enumerable.Range(1, 100).ToArray(),
i => i.ToString()
)
)
);
using static IronRuby.Ruby;
class Print1To100WithoutLoopsDemo
{
static void Main() =>
CreateEngine().Execute("(1..100).each {|i| System::Console.write_line i }");
}
Hé, pourquoi pas
Console.WriteLine('1');
Console.WriteLine('2');
...
Console.WriteLine('100');
... ou auriez-vous accepté une solution récursive?
EDIT: ou vous pouvez le faire et utiliser une variable:
int x = 1;
Console.WriteLine(x);
x+=1;
Console.WriteLine('2');
x+=1;
...
x+=1
Console.WriteLine('100');
Enumerable.Range(1, 100)
.Select(i => i.ToString())
.ToList()
.ForEach(s => Console.WriteLine(s));
Je ne sais pas si cela compte car la boucle est un peu cachée, mais si c'est légitime, c'est une solution idiomatique au problème. Sinon, vous pouvez le faire.
int count = 1;
top:
if (count > 100) { goto bottom; }
Console.WriteLine(count++);
goto top;
bottom:
Bien sûr, c’est bien ce qu’une boucle sera traduite de toute façon, mais il est très mal vu ces jours-ci d’écrire du code comme celui-ci.
Pas de boucles, pas de récursivité, juste un tableau de fonctions de type hashtable pour choisir comment créer une branche:
using System;
using System.Collections.Generic;
namespace Juliet
{
class PrintStateMachine
{
int state;
int max;
Action<Action>[] actions;
public PrintStateMachine(int max)
{
this.state = 0;
this.max = max;
this.actions = new Action<Action>[] { IncrPrint, Stop };
}
void IncrPrint(Action next)
{
Console.WriteLine(++state);
next();
}
void Stop(Action next) { }
public void Start()
{
Action<Action> action = actions[Math.Sign(state - max) + 1];
action(Start);
}
}
class Program
{
static void Main(string[] args)
{
PrintStateMachine printer = new PrintStateMachine(100);
printer.Start();
Console.ReadLine();
}
}
}
Enumerable.Range(1, 100).ToList().ForEach(i => Console.WriteLine(i));
Voici une ventilation de ce qui se passe dans le code ci-dessus:
Considération de performance
L'appel de la liste des tâches provoquera l'allocation de mémoire pour tous les éléments (dans l'exemple ci-dessus, 100 ints). Cela signifie O(N) complexité d'espace. Si cela pose un problème dans votre application, c’est-à-dire si la plage d’entiers peut être très élevée, évitez ToList et énumérez directement les éléments.
Malheureusement, ForEach ne fait pas partie des extensions IEnumerable fournies prêtes à l'emploi (d'où la nécessité de convertir en liste dans l'exemple ci-dessus). Heureusement c'est assez facile à créer:
static class EnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> items, Action<T> func)
{
foreach (T item in items)
{
func(item);
}
}
}
Avec l'extension IEnumerable ci-dessus en place, vous pouvez simplement appeler ForEach avec un lambda à tous les endroits où vous devez appliquer une action à un IEnumerable. Alors maintenant, l'exemple original ressemble à ceci:
Enumerable.Range(1, 100).ForEach(i => Console.WriteLine(i));
La seule différence est que nous n'appelons plus ToList, ce qui entraîne une utilisation constante de l'espace (O (1)) ... ce qui constituerait un gain notable si vous traitez un très grand nombre d'éléments.
Au moment où je réponds à cette question, quelqu'un l'aura déjà, alors voici le cas, avec le crédit de Caleb:
void Main()
{
print(0, 100);
}
public void print(int x, int limit)
{
Console.WriteLine(++x);
if(x != limit)
print(x, limit);
}
Juste pour l'interprétation littérale laide:
Console.WriteLine("numbers from 1 to 100 without using loops, ");
(tu peux rire maintenant ou plus tard, ou pas)
Avec expressions régulières
using System.Text.RegularExpressions;
public class Hello1
{
public static void Main()
{
// Count to 128 in unary
string numbers = "x\n";
numbers += Regex.Replace(numbers, "x+\n", "x$&");
numbers += Regex.Replace(numbers, "x+\n", "xx$&");
numbers += Regex.Replace(numbers, "x+\n", "xxxx$&");
numbers += Regex.Replace(numbers, "x+\n", "xxxxxxxx$&");
numbers += Regex.Replace(numbers, "x+\n", "xxxxxxxxxxxxxxxx$&");
numbers += Regex.Replace(numbers, "x+\n", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$&");
numbers += Regex.Replace(numbers, "x+\n", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$&");
// Out of 1..128, select 1..100
numbers = Regex.Match(numbers, "(.*\n){100}").Value;
// Convert from unary to decimal
numbers = Regex.Replace(numbers, "x{10}", "<10>");
numbers = Regex.Replace(numbers, "x{9}", "<9>");
numbers = Regex.Replace(numbers, "x{8}", "<8>");
numbers = Regex.Replace(numbers, "x{7}", "<7>");
numbers = Regex.Replace(numbers, "x{6}", "<6>");
numbers = Regex.Replace(numbers, "x{5}", "<5>");
numbers = Regex.Replace(numbers, "x{4}", "<4>");
numbers = Regex.Replace(numbers, "x{3}", "<3>");
numbers = Regex.Replace(numbers, "x{2}", "<2>");
numbers = Regex.Replace(numbers, "x{1}", "<1>");
numbers = Regex.Replace(numbers, "(<10>){10}", "<100>");
numbers = Regex.Replace(numbers, "(<10>){9}", "<90>");
numbers = Regex.Replace(numbers, "(<10>){8}", "<80>");
numbers = Regex.Replace(numbers, "(<10>){7}", "<70>");
numbers = Regex.Replace(numbers, "(<10>){6}", "<60>");
numbers = Regex.Replace(numbers, "(<10>){5}", "<50>");
numbers = Regex.Replace(numbers, "(<10>){4}", "<40>");
numbers = Regex.Replace(numbers, "(<10>){3}", "<30>");
numbers = Regex.Replace(numbers, "(<10>){2}", "<20>");
numbers = Regex.Replace(numbers, "(<[0-9]{3}>)$", "$1<00>");
numbers = Regex.Replace(numbers, "(<[0-9]{2}>)$", "$1<0>");
numbers = Regex.Replace(numbers, "<([0-9]0)>\n", "$1\n");
numbers = Regex.Replace(numbers, "<([0-9])0*>", "$1");
System.Console.WriteLine(numbers);
}
}
Le résultat:
# => 1
# => 2
# ...
# => 99
# => 100
Je peux penser de deux manières. L'un d'eux implique environ 100 lignes de code!
Il existe un autre moyen de réutiliser un peu de code plusieurs fois sans utiliser une boucle while/for ...
Astuce: Créez une fonction imprimant les nombres de 1 à N. Il devrait être facile de la faire fonctionner pour N = 1. Ensuite, réfléchissez à la façon de la faire fonctionner pour N = 2.
Méthode A:
Console.WriteLine('1');
Console.WriteLine('print 2');
Console.WriteLine('print 3');
...
Console.WriteLine('print 100');
Méthode B:
func x (int j)
{
Console.WriteLine(j);
if (j < 100)
x (j+1);
}
x(1);
Juste LINQ il ...
Console.WriteLine(Enumerable.Range(1, 100)
.Select(s => s.ToString())
.Aggregate((x, y) => x + "," + y));
Une méthode totalement inutile:
int i = 1;
System.Timers.Timer t = new System.Timers.Timer(1);
t.Elapsed += new ElapsedEventHandler(
(sender, e) => { if (i > 100) t.Enabled = false; else Console.WriteLine(i++); });
t.Enabled = true;
Thread.Sleep(110);
Je peux penser de deux manières:
Console.WriteLine
goto
dans une déclaration switch
public void Main()
{
printNumber(1);
}
private void printNumber(int x)
{
Console.WriteLine(x.ToString());
if(x<101)
{
x+=1;
printNumber(x);
}
}
class Program
{
static int temp = 0;
public static int a()
{
temp = temp + 1;
if (temp == 100)
{
Console.WriteLine(temp);
return 0;
}
else
Console.WriteLine(temp);
Program.a();
return 0;
}
public static void Main()
{
Program.a();
Console.ReadLine();
}
}
La manière cool et amusante:
static void F(int[] array, int n)
{
Console.WriteLine(array[n] = n);
F(array, n + 1);
}
static void Main(string[] args)
{
try { F(new int[101], 1); }
catch (Exception e) { }
}
[Test]
public void PrintNumbersNoLoopOrRecursionTest()
{
var numberContext = new NumberContext(100);
numberContext.OnNumberChange += OnNumberChange(numberContext);
numberContext.CurrentNumber = 1;
}
OnNumberChangeHandler OnNumberChange(NumberContext numberContext)
{
return (o, args) =>
{
if (args.Counter > numberContext.LastNumber)
return;
Console.WriteLine(numberContext.CurrentNumber);
args.Counter += 1;
numberContext.CurrentNumber = args.Counter;
};
}
public delegate void OnNumberChangeHandler(object source, OnNumberChangeEventArgs e);
public class NumberContext
{
public NumberContext(int lastNumber)
{
LastNumber = lastNumber;
}
public event OnNumberChangeHandler OnNumberChange;
private int currentNumber;
public int CurrentNumber
{
get { return currentNumber; }
set {
currentNumber = value;
OnNumberChange(this, new OnNumberChangeEventArgs(value));
}
}
public int LastNumber { get; set; }
public class OnNumberChangeEventArgs : EventArgs
{
public OnNumberChangeEventArgs(int counter)
{
Counter = counter;
}
public int Counter { get; set; }
}
Se sentir un peu vilain poster ceci:
private static void Main()
{
AppDomain.CurrentDomain.FirstChanceException += (s, e) =>
{
var frames = new StackTrace().GetFrames();
Console.Write($"{frames.Length - 2} ");
var frame = frames[101];
};
throw new Exception();
}
class Program
{
static Timer s = new Timer();
static int i = 0;
static void Main(string[] args)
{
s.Elapsed += Restart;
s.Start();
Console.ReadLine();
}
static void Restart(object sender, ElapsedEventArgs e)
{
s.Dispose();
if (i < 100)
{
Console.WriteLine(++i);
s = new Timer(1);
s.Elapsed += Restart;
s.Start();
}
}
}
Vous devez remarquer que jePASutilise la récursivité.
C’est plus ou moins un pseudo-code que j’ai pas fait c # depuis des années, le PS tournant sous 1 heure de sommeil, j’ai peut-être tort.
int i = 0;
public void printNum(j){
if(j > 100){
break;
} else {
print(j);
printNum(j + 1);
}
}
public void main(){
print(i);
printNum(i + 1);
}
PrintNum(1);
private void PrintNum(int i)
{
Console.WriteLine("{0}", i);
if(i < 100)
{
PrintNum(i+1);
}
}
namespace ConsoleApplication2 {
class Program {
static void Main(string[] args) {
Print(Enumerable.Range(1, 100).ToList(), 0);
Console.ReadKey();
}
public static void Print(List<int> numbers, int currentPosition) {
Console.WriteLine(numbers[currentPosition]);
if (currentPosition < numbers.Count - 1) {
Print(numbers, currentPosition + 1);
}
}
}
}
Ma solution est dans le fil 2045637 , qui pose la même question pour Java.