Ich versuche, mit C # Zahlen von 1 bis 100 zu drucken, ohne Schleifen zu verwenden. Irgendwelche Hinweise?
Rekursion vielleicht?
public static void PrintNext(i) {
if (i <= 100) {
Console.Write(i + " ");
PrintNext(i + 1);
}
}
public static void Main() {
PrintNext(1);
}
Keine Schleifen, keine Bedingungen und keine hartcodierte Literalausgabe, auch bekannt als "FTW teilen und erobern" -Lösung:
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(); }
}
Alternativer Ansatz:
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');
Einer noch:
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 }");
}
Hey, warum nicht?
Console.WriteLine('1');
Console.WriteLine('2');
...
Console.WriteLine('100');
... Oder hätten Sie eine rekursive Lösung akzeptiert?
EDIT: oder Sie könnten dies tun und eine Variable verwenden:
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));
Ich bin mir nicht sicher, ob dies als versteckte Schleife gilt, aber wenn es echt ist, ist es eine idiomatische Lösung für das Problem. Ansonsten kannst du das machen.
int count = 1;
top:
if (count > 100) { goto bottom; }
Console.WriteLine(count++);
goto top;
bottom:
Natürlich ist dies effektiv das, in das eine Schleife übersetzt wird, aber es ist heutzutage sicherlich verpönt, Code wie diesen zu schreiben.
Keine Schleifen, keine Rekursion, nur eine Art Hash-Tabelle mit einer Reihe von Funktionen, mit denen Sie auswählen können, wie verzweigt werden soll:
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));
Hier ist eine Aufschlüsselung dessen, was im obigen Code passiert:
Überlegung zur Leistung
Durch den Aufruf von ToList wird allen Elementen Speicher zugewiesen (im obigen Beispiel 100 Zoll). Dies bedeutet O(N) Raumkomplexität. Wenn dies ein Problem in Ihrer App ist, d. H. Wenn der Bereich der Ganzzahlen sehr hoch sein kann, sollten Sie ToList vermeiden und die Elemente direkt aufzählen.
Leider ist ForEach nicht Teil der IEnumerable-Erweiterungen, die standardmäßig bereitgestellt werden (daher muss im obigen Beispiel nach List konvertiert werden). Glücklicherweise ist das ziemlich einfach zu erstellen:
static class EnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> items, Action<T> func)
{
foreach (T item in items)
{
func(item);
}
}
}
Mit der obigen IEnumerable-Erweiterung können Sie jetzt an allen Stellen, an denen Sie eine Aktion auf einen IEnumerable anwenden müssen, ForEach einfach mit einem Lambda aufrufen. Das ursprüngliche Beispiel sieht also so aus:
Enumerable.Range(1, 100).ForEach(i => Console.WriteLine(i));
Der einzige Unterschied besteht darin, dass wir ToList nicht mehr aufrufen. Dies führt zu einer konstanten (O (1)) Speicherplatzbelegung. Dies wäre ein beachtlicher Gewinn, wenn Sie eine sehr große Anzahl von Elementen verarbeiten würden.
Wenn ich das beantworte, wird es schon jemand haben, also ist es hier auf jeden Fall gutgeschrieben für Caleb:
void Main()
{
print(0, 100);
}
public void print(int x, int limit)
{
Console.WriteLine(++x);
if(x != limit)
print(x, limit);
}
Nur für die hässliche wörtliche Auslegung:
Console.WriteLine("numbers from 1 to 100 without using loops, ");
(Sie können jetzt oder später lachen oder nicht)
Mit regulären Ausdrücken
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);
}
}
Die Ausgabe:
# => 1
# => 2
# ...
# => 99
# => 100
Ich kann mir zwei Möglichkeiten vorstellen. Eine davon enthält ungefähr 100 Codezeilen!
Es gibt eine andere Möglichkeit, ein bisschen Code mehrmals wiederzuverwenden, ohne eine while/for-Schleife zu verwenden ...
Tipp: Machen Sie eine Funktion, die die Zahlen von 1 bis N ausgibt. Es sollte einfach sein, sie für N = 1 arbeiten zu lassen. Dann überlegen Sie, wie Sie sie für N = 2 arbeiten lassen.
Methode A:
Console.WriteLine('1');
Console.WriteLine('print 2');
Console.WriteLine('print 3');
...
Console.WriteLine('print 100');
Methode B:
func x (int j)
{
Console.WriteLine(j);
if (j < 100)
x (j+1);
}
x(1);
Einfach LINQ it ...
Console.WriteLine(Enumerable.Range(1, 100)
.Select(s => s.ToString())
.Aggregate((x, y) => x + "," + y));
Eine völlig unnötige Methode:
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);
Ich kann auf zwei Arten denken:
Console.WriteLine
goto
in einer switch
-Anweisungpublic 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();
}
}
Die coole und lustige Art:
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; }
}
Ich fühle mich ein bisschen ungezogen, wenn ich das poste:
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();
}
}
}
Sie müssen feststellen, dass ichNICHTeine Rekursion verwende.
Dies ist mehr oder weniger Pseudo-Code, den ich seit Jahren nicht mehr gemacht habe. PS läuft mit 1 Stunde Schlaf, also könnte ich mich irren.
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);
}
}
}
}
Meine Lösung ist in Thread 2045637 , die die gleiche Frage für Java stellt.