【问题标题】:Print numbers in specific range without using any loop or conditions (Java)在不使用任何循环或条件的情况下打印特定范围内的数字(Java)
【发布时间】:2017-11-08 00:11:50
【问题描述】:

也许解决这类问题的第一个想法是递归函数,但在没有任何条件的情况下编写递归函数也是一个挑战。

我尝试了这种方法来打印从 10 到 60 的数字:

public static void printNumbers(int n){
       int divisonByZero = 1 / (61 - n);
       System.out.println(n);
       printNumbers(n+1);
}     
public static void main(String[] args) {
       printNumbers(10);
}   

但是在没有异常处理的情况下到达号码61会崩溃

即使尝试捕获 算术异常,它仍然不是一个可取的解决方案,因为它正在处理异常(运行时错误)。

我认为使用递归函数的主要问题是停止条件。

我还读到,在 C++ 中有一种方法是通过创建一个带有静态变量 counter 的类并对其进行初始化,然后递增 counter 变量并在构造函数中打印它,之后实例化类 counter 的对象数量将打印这些数字.

我们将不胜感激任何解决这一挑战的建议解决方案。

【问题讨论】:

  • 你可以使用IntStream类的range方法吗?
  • System.out.printLine("10,11,12,13,14,15...60");?如果在您编写代码之前确定了范围,那么这至少可以工作。
  • 顺便说一句,正如@DawoodibnKareem 所说,如果您能够使用IntStream,您可以在Java8 中执行以下操作。 IntStream.range(1, 10).forEach(System.out::println); 但是,它使用forEach
  • 两个线程。第一个线程使用递归将它们放入数组中,并使用 % 运算符确保它们不会溢出数组。另一个线程休眠一会儿,打印数组,然后杀死第一个线程。
  • 你可以用 lambda 来做。将所有内容都转换为 lambda 演算并以这种方式解决。您的条件和循环将是匿名函数调用。请参阅this video 获取灵感。

标签: java loops recursion


【解决方案1】:

对正常的程序流使用异常是一种糟糕的形式,但这很有效。最终会出现除以零的异常,这是退出的信号。

public class App {

    public static void main(String[] args) {
        App app = new App();
        try {
            app.print(10, 60);
        } catch (ArithmeticException ae) {
            // ignore
        }
    }

    private void print(int next, int until) {
        System.out.println(next);
        assertNotEndOfRange(next, until);
        print(++next, until);
    }

    private int assertNotEndOfRange(int next, int until) {
        return 0 / (until - next);
    }

}

【讨论】:

  • catch 内部会用instanceof 做一个if → 有条件的 → 不回答问题
【解决方案2】:

您的程序将崩溃,因为 61int divisonByZero = 1 / (61 - n); 将变为 int divisonByZero = 1 / 0; Which is a division by zero and raises an exception.

您可以使用 try-catch 来捕获异常,但我不知道您是否将此视为条件。为此使用异常也是不好的做法。但您将在下面找到如何实现这样的版本。

public class Main {

   public static void printNumbers(int n, int stop) {
       System.out.println(n);
       try {
          int divisonByZero = 1 / (stop - n);
          printNumbers(n + 1, stop);
       } catch (ArithmeticException e) {
          System.out.println("program is terminated");
       }
   }

   public static void main(String[] args) {
       printNumbers(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
   }
}

【讨论】:

  • 感谢好建议。但正如你所说,为此使用例外是不好的做法。即使使用 try catch 它仍然不是一个更可取的解决方案,因为它正在处理一个被零除的异常(运行时错误)。
【解决方案3】:

你可以这样做:(取自answer的想法)

public class Application {

    public static void main(String[] args) {
        Print40Numbers();
        Print10Numbers();

    }

    private static int currentNumber = 10;

    private static void Print1Number() { System.out.println(currentNumber++); }
    private static void Print2Numbers() { Print1Number(); Print1Number(); }    
    private static void Print5Numbers() { Print2Numbers(); Print2Numbers(); Print1Number(); }   
    private static void Print10Numbers() { Print5Numbers();Print5Numbers();}
    private static void Print20Numbers() { Print10Numbers();Print10Numbers();}
    private static void Print40Numbers() { Print20Numbers();Print20Numbers();}



}

【讨论】:

  • 好主意。它更像是在手动方法中实现递归算法,而无需像在递归函数中那样设置停止条件。
  • @Colt 这是一个静态解决方案,如果你想调整间隔,你必须重新编译整个东西。在这种情况下,只需对要打印的每个值进行硬编码并使用它就可以更容易。
  • 我在这里闻到了 Prolog 和类似声明的味道。 :)
【解决方案4】:

这是一个使用哈希映射、位运算符、相等表达式和反射的解决方案:

import java.lang.reflect.*;
import java.util.*;

public class Range
{

  private final Map<Boolean, Integer> truth;

  Range()
  {
    truth = new HashMap<>();
    truth.put(true, 0);
    truth.put(false, 1);
  }

  public void printRange(int start, int stop) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
  {
    print1(start, stop);
  }

  public void print1(Integer start, Integer stop) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
  {
    int quit = start ^ stop;
    int method = truth.get(quit == 0);
    System.out.println(start);

    String whichMethod = Integer.toString(method);
    Method toCall = this.getClass().getMethod("print" + whichMethod, Integer.class, Integer.class);
    toCall.invoke(this, start + 1, stop);
  }

  public void print0(Integer start, Integer stop)
  {
    System.exit(0);
  }

  public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
  {
    Range range = new Range();
    range.printRange(-10, 60);
  }
}

好的,这是一种方法,这是一种更面向对象的方法,您不使用额外的东西。

import java.util.*;

public class Range
{

  interface Printer
  {
    void print(int start, int end);
  }

  private final Map<Boolean, Printer> truth;

  Range()
  {
    truth = new HashMap<>();
    truth.put(true, new Quit());
    truth.put(false, new KeepGoing());
  }

  public void printRange(int start, int stop)
  {
    truth.get(false).print(start, stop);
  }

  private class KeepGoing implements Printer
  {
    public void print(int start, int stop)
    {
      int quit = start ^ stop;
      Printer method = truth.get(quit == 0);
      System.out.println(start);

      method.print(start + 1, stop);
    }
  }

  private class Quit implements Printer
  {
    public void print(int start, int stop)
    {
      return;
    }
  }

  public static void main(String[] args)
  {
    Range range = new Range();
    range.printRange(-10, 60);
  }
}

【讨论】:

  • 谢谢!您能否更详细地解释您的第一种方法,以便我能很好地理解它。我认为你是唯一可以解决这一挑战的人。
  • @Colt 第一种方法使用reflection。该链接是用于反射的 java 路径。看看这个。基本上我使用一个字符串来识别这个类中要调用的方法。 HashMap 的值方面是排序的仲裁者。通过附加方法的名称,做出决定。当该退出时,我使用System.exit 并从jvm 下方拉出地毯。恕我直言,第二个解决方案比第一个更受欢迎。
  • 请注意,在任一实现中都不需要 XOR,^。等式表达式可以只是start == stop,并一起删除quit 变量。
  • == → 有条件的 → 不回答问题
  • @D.Kovács == 不是有条件的。这是一个等式表达式。检查JLS。等式表达式的结果是一个布尔值。
【解决方案5】:

您的代码

public static void printNumbers(int n){
       int divisonByZero = 1 / (61 - n);
                               ^^^(1/61-61) => 1/0 => Dividedbyzero error
       System.out.println(n);
       printNumbers(n+1);
}     
public static void main(String[] args) {
       printNumbers(10);
}

你说程序到了 61 就崩溃了。

这是一个运行时错误

更具体地说是ArithmeticException

如何?

你有这种情况

int divisionByZero = 1 / (61-n);

n达到61时,则1 / (61 - 61)

等于1 / 0,这是一个错误。

要阻止这种情况,您必须实现 try...catch 以捕获算术异常

所以,代码将是

public static void printNumbers(int n){
       try{
           int divisonByZero = 1 / (61 - n);
           System.out.println(n);
           printNumbers(n+1);
       }catch(ArithmeticException e){
       }
}     
public static void main(String[] args) {
       printNumbers(10);
}

【讨论】:

  • 感谢您的澄清。但是为此使用异常是不好的做法。即使使用 try catch 它仍然不是一个可取的解决方案,因为它正在处理除以零的异常(运行时错误)。
【解决方案6】:

我认为这在理论上是不可行的。无论哪种方式,您都必须有一个停止条件。 可以是:

  • if
  • 带有三元运算符的return
  • 异常检查(内部执行instanceof
  • 一个 lambda(存在很多解决方案,其中大多数可能涉及一个或多个隐式循环和一个或多个隐式 ifs)

如果您深入到人类可理解的最深层次(也称为汇编),您将肯定在生成的程序中至少有一个 jmp。这个事实与您使用的高级语言无关。

【讨论】:

  • 我同意你的看法。
【解决方案7】:

基于@Imposter 的回答,一个精简但可读的代码的版本

class Sandbox
{
    public static void main(String args[]) throws Exception
    {
        System.out.println(getfalse(10, 60));
    }

    public static String getfalse(Integer start, Integer stop) throws Exception
    {
        return
            start + "\n" +
            Sandbox.class.getMethod("get" + (start == stop), Integer.class, Integer.class)
            .invoke(Sandbox.class, start+1, stop);
    }

    public static String gettrue(Integer start, Integer stop)
    {
        return "";
    }
}

【讨论】:

  • 谢谢。您能解释一下您的方法以及getfalse()gettrue() 方法的工作原理吗?
  • getfalsestop 尚未到达时被调用,它连接当前号码并调用gettrue 如果它是最后一个要处理的号码(start == stop ) 或调用getfalse 如果尚未达到stop (start != stop) 等...
  • start == stop → 有条件的 → 不回答问题
  • ToYonos 非常感谢。您的解决方案完美无缺,干净优雅。值得赏金。还要感谢 @Imposter 提出这个解决方案的想法。
  • 我不同意这个解决方案,== 本质上是一个if(生成的字节码与标准ifne 语句中的ifne 相同)。
【解决方案8】:

为什么不使用简单的流?

IntStream.range(10, 60).forEach(System.out::println)

Stream 不是循环,但您可以说“有点”。在除以零的情况下 - 您可以将除法语句包装在 try 块中。并退出没有错误。

try { 
    int divisonByZero = 1 / (61 - n);
    ...
catch (ArithmeticException e) {
    // exit or return something to stop recursion
}

【讨论】:

  • 谢谢。也许IntStream.range(10, 60) 可以解决这个问题,但.forEach() 被认为是一种循环,不允许解决问题。也正如我在问题中所说,即使尝试捕获算术异常,它仍然不是一个可取的解决方案,因为它正在处理异常(运行时错误)。
  • Colt,这是关于干净的代码吗?如果是这样,这是我在这里看到的唯一可接受的解决方案。它干净、优雅、流畅,传达了程序员的意图,没有显式循环、if 条件和异常处理。恕我直言,您关于希望摆脱隐式 forEach 循环的评论对我来说是无稽之谈。
  • @kriegaex .forEach() 是 java 8 中的一种新方法,我不允许在解决方案中使用它,因为它被认为是一个以不同方式实现的 for 循环。
  • 我不在乎你是否被允许在你的深奥任务中使用它。不过,我确实关心干净的代码。我在这里看到的一些人为的解决方案来解决你的挑战让我的脚趾甲卷曲。可能与否,这不是要走的路。如果你想要一个没有循环和 if 条件的好程序流,只需做一点 OOD 并将这些细节隐藏在一个方法中,然后调用该方法。不过,引擎中的机械最终必须是某种东西。
【解决方案9】:

您可以使用信号量来限制递归计数:

import java.util.concurrent.Semaphore;

public class PrintNumbers extends Thread 
{
  static int start = 10;
  static int end = 60;

  static Semaphore available = new Semaphore(end - start, true);
  static Semaphore completed = new Semaphore(end - start, true);

  public static void main(String[] args) throws Exception {
    completed.drainPermits();  
    (new PrintNumbers()).start(); //Start watcher thread
    counter(start);
  }

  // Recursive function for counting
  public static void counter(int count) throws Exception{
    System.out.println(count);
    count++;
    completed.release();
    available.acquire(); // Will stop here when there is no more to count
    counter(count);
  }  

  public void run() {
    completed.acquireUninterruptibly(end - start);
    System.exit(0);  // Terminate process
  }
}

PrintNumbers 类在计数完成后启动一个观察线程来终止进程。

【讨论】:

  • 内部使用条件句→不是问题的答案
  • 您能说得更具体些吗?哪个语句在内部使用条件?
  • 如果您关心 Semaphore 类中的 if 语句,单独的 System.out.println 函数也包含几个条件。如果没有内部条件,您将无法在控制台上打印单个数字。我认为这里的标准是关于避免明确使用条件。
  • 很好的解决方案!谢谢。你能解释一下它是如何工作的吗?
  • @OmerKocaoglu 我不同意你的观点:如果你不关心内部if-s,那么IntStream 与具有反射或异常或信号的解决方案一样好。
【解决方案10】:

我有三个解决方案,源代码中没有循环或条件

第一个使用 JavaScript 引擎评估字符串命令,该命令在编译时存储在 byte[] 中。

import javax.script.ScriptEngineManager;
import java.nio.charset.StandardCharsets;


public class PrintNumbers
{
    public static void main(String... args) throws Exception
    {
        byte[] iCantSeeALoopHere = new byte[]{102, 111, 114, 32, 40, 105, 32, 61, 32, 49, 48, 59, 32, 105, 32, 60, 61, 32, 54, 48, 59, 32, 105, 43, 43, 41, 32, 123, 32, 112, 114, 105, 110, 116, 40, 105, 41, 59, 32, 125};
        new ScriptEngineManager().getEngineByName("JavaScript").eval(new String(iCantSeeALoopHere, StandardCharsets.UTF_8));
    }
}

第二个将 .class-File 写入主目录并执行它。

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;


public class PrintNumbers
{
    public static void main(String... args) throws Exception
    {
        byte[] iCantSeeALoopHere = new byte[]{-54, -2, -70, -66, 0, 0, 0, 52, 0, 31, 10, 0, 5, 0, 17, 9, 0, 18, 0, 19, 10, 0, 20, 0, 21, 7, 0, 22, 7, 0, 23, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 4, 109, 97, 105, 110, 1, 0, 22, 40, 91, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 41, 86, 1, 0, 13, 83, 116, 97, 99, 107, 77, 97, 112, 84, 97, 98, 108, 101, 1, 0, 10, 69, 120, 99, 101, 112, 116, 105, 111, 110, 115, 7, 0, 24, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 17, 80, 114, 105, 110, 116, 78, 117, 109, 98, 101, 114, 115, 46, 106, 97, 118, 97, 12, 0, 6, 0, 7, 7, 0, 25, 12, 0, 26, 0, 27, 7, 0, 28, 12, 0, 29, 0, 30, 1, 0, 12, 80, 114, 105, 110, 116, 78, 117, 109, 98, 101, 114, 115, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 19, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 69, 120, 99, 101, 112, 116, 105, 111, 110, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 121, 115, 116, 101, 109, 1, 0, 3, 111, 117, 116, 1, 0, 21, 76, 106, 97, 118, 97, 47, 105, 111, 47, 80, 114, 105, 110, 116, 83, 116, 114, 101, 97, 109, 59, 1, 0, 19, 106, 97, 118, 97, 47, 105, 111, 47, 80, 114, 105, 110, 116, 83, 116, 114, 101, 97, 109, 1, 0, 7, 112, 114, 105, 110, 116, 108, 110, 1, 0, 4, 40, 73, 41, 86, 0, 33, 0, 4, 0, 5, 0, 0, 0, 0, 0, 2, 0, 1, 0, 6, 0, 7, 0, 1, 0, 8, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 1, 0, 9, 0, 0, 0, 6, 0, 1, 0, 0, 0, 1, 0, -119, 0, 10, 0, 11, 0, 2, 0, 8, 0, 0, 0, 74, 0, 2, 0, 2, 0, 0, 0, 23, 16, 10, 60, 27, 16, 60, -93, 0, 16, -78, 0, 2, 27, -74, 0, 3, -124, 1, 1, -89, -1, -16, -79, 0, 0, 0, 2, 0, 9, 0, 0, 0, 18, 0, 4, 0, 0, 0, 5, 0, 9, 0, 7, 0, 16, 0, 5, 0, 22, 0, 9, 0, 12, 0, 0, 0, 9, 0, 2, -4, 0, 3, 1, -6, 0, 18, 0, 13, 0, 0, 0, 4, 0, 1, 0, 14, 0, 1, 0, 15, 0, 0, 0, 2, 0, 16};
        Path javaClassFile = Paths.get(System.getProperty("user.home"), "PrintNumbers.class").toAbsolutePath();
        Files.write(javaClassFile, iCantSeeALoopHere);

        new ProcessBuilder(
                "java",
                "-cp",
                javaClassFile.getParent().toString(),
                javaClassFile.getFileName().toString().replace(".class", "")
        ).inheritIO().start().waitFor();

        Files.delete(javaClassFile);
    }
}

第三个使用getOrDefault-Map 的方法有类似条件:

import java.util.Map;
import java.util.HashMap;
import java.util.function.BiConsumer;

public class PrintNumbers
{
    private static Map<Integer, BiConsumer<Integer, Integer>> funcMap;

    public static void main(String[] args)
    {
      funcMap = new HashMap<>();
      funcMap.put(0, PrintNumbers::doNothing);

      printNumbers(10, 60);
    }

    private static void printNumbers(int curr, int end)
    {
      System.out.println(curr);

      BiConsumer<Integer, Integer> next = funcMap.getOrDefault(end - curr, PrintNumbers::printNumbers);
      next.accept(curr + 1, end);
    }

    private static void doNothing(int a, int b) {}
}

【讨论】:

    【解决方案11】:

    这是我的代码...从冒名顶替者那里得到想法。谢谢@imposter

    package com.test;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.Map;
    
    public class StackOverFlow {
        Map<Integer, String> methodCall = new HashMap<>();
        static int diff;
        static int reminder;
        static int methodNumber;
        public static void print1(Integer start, Integer end) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
            diff= (end.intValue()-1)-start.intValue();
            reminder = diff % 2;
            methodNumber = reminder+1;
               System.out.println(start.intValue());
               //System.out.println("methodNumber   " + methodNumber);
               Method call =StackOverFlow.class.getDeclaredMethod("print"+methodNumber,Integer.class,Integer.class);
               call.invoke(StackOverFlow.class, start.intValue()+1,end);
    
        }
        public static void print0(Integer start, Integer end){
    
               //System.out.println(n.intValue());
               System.exit(0);
    
        }
        public static void print2(Integer start, Integer end) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
            diff= (end.intValue()-1)-start.intValue();
            reminder = diff % 2;
            methodNumber = reminder+1;
    
               System.out.println(start.intValue());
               //System.out.println("methodNumber   " + methodNumber);
               Method call =StackOverFlow.class.getDeclaredMethod("print"+methodNumber,Integer.class,Integer.class);
               call.invoke(StackOverFlow.class, start.intValue()+1,end);
    
        } 
    
        public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    
               print1(Integer.valueOf(10),Integer.valueOf(60));
        }
    
    }
    

    【讨论】:

    • 我知道这是冒名顶替者所做的复制品/.. 但只是想试试这个
    • 冒名顶替者的代码有同样的问题,它调用了使用 if 语句的 Launcher.loadClass
    • 但是加载类是每次都被调用还是只有在我们使用反射时才会发生
    【解决方案12】:

    您可以使用java.util.BitSet,它是一个代表大量正整数的类。

    class Number {
        public static void main(String[] args) {
            int n = 100;
            String set = new java.util.BitSet() {{ set(1, n+1); }}.toString();
            System.out.append(set, 1, set.length()-1);
        }
    }
    

    【讨论】:

      【解决方案13】:

      首先,您为什么需要解决任何此类问题?是什么禁止您使用标准周期甚至标准“IF”? ...在我看来,这听起来只是一个学者假设性的讨论。 :-/

      无论如何:

      如前所述,每个可重复序列都需要一个“IF”,即停止条件:它肯定会在运行时出现在处理器上(想象一下 ASM 指令)。唯一的区别是,IF 是在哪个抽象/架构级别上引起的:

      • 直接在代码中(作为基本级别,但此处禁止,在问题中)..无论是语法上真实的IF,还是三元组?:
      • ...
      • 或即在 JVM 继承机制中,在可能性范围的另一个极端:多态性执行 IF,但在内部是隐式的。 (有人在这里提到过吗?)我想象两个变异对象类,实现相同的方法:

        • 在一种实施方式中,更改后的方法会出现硬停,
        • 另一个只是“运行时类”的递归调用。

        这样的方法会非常简短直接。

        ...这些可能是抽象类的实现:由您决定。

      不过,无论哪种解决方案实施都不会改变事实:IF 仍然存在,某处。

      【讨论】:

      • 任何参考资料?
      • 你确定吗?我很确定我的例子没有做任何事情。如果需要,我可以用 c 编写。
      • @KyleBerezin:我在您的代码中看到了这一点:“doList[b].doIt(start + 1, stop);” - 所以,你说“没有如果”?严重地?事实上,IF 被包裹/隐藏并不意味着它可能会消失。当然,内部某处有一个 IF:即重载机制在内部肯定使用 IF。 (即口译员)
      【解决方案14】:

      我可以使用隐式数字转换吗?

      public class NoLoopNoConditional {
          @SuppressWarnings( "unchecked" )
          private final Consumer< Integer >[] afn =
              ( Consumer< Integer >[] )new Consumer[ 2 ];
          private final double dDelta;
          private final int iLow;
      
          public NoLoopNoConditional( int iLow, int iHigh ) {
              this.iLow = iLow;
              this.dDelta = ( double )iHigh + 1 - iLow;
              // load the recursive and terminal cases
              afn[ 0 ] = ( i ) -> {};
              afn[ 1 ] = ( i ) -> {
                  System.out.println( i );
                  recur( i + 1 );
              };
          }
      
          // returns 1 until i exceeds iHigh, then returns 0
          private int choice( int i ) {
              return ( int )( ( dDelta + dDelta - i + iLow ) / ( dDelta + 1 ) );
          }
      
          private void recur( int i ) {
              afn[ choice( i ) ].accept( i );
          }
      
          public static void main( String[] args ) {
              // grab the parameters
              // throws exception if wrong # of args or can't parse. no conditionals
              int iLow = Integer.parseInt( args[ 0 ] ), iHigh = Integer.parseInt( args[ 1 ] );
      
              // go for it
              new NoLoopNoConditional( iLow, iHigh ).recur( iLow );
          }
      }
      

      唯一的缺陷是大范围会因为太多(尾)递归调用而导致StackOverflowError

      【讨论】:

      • 我注意到,如果你颠倒高低,说试着让这个环绕,就像 2147483647 为低,-2147483648 为高,它会抛出一个java.lang.IndexOutOfBoundsException而不是像它应该的那样包装。我的实现处理这个。我还是投了赞成票,因为它很酷!
      • ArrayList.add(int var1, E var2) 使用使用 if 的 rangeCheckForAdd。虽然这是一个非常酷的答案。
      • 现在这很愚蠢。我的第一个版本有一个常规数组,但我不喜欢所有的强制转换和原始类型。
      • 哦,我的错,我现在明白了。是的,它适用于数组。看看我是怎么做的,我做了非常相似的方法。 (虽然可能有点丑?)
      • 把它变成一个数组只是为了完成它,叹息。
      【解决方案15】:

      您可以按如下方式使用 Java 8 流:

      import java.util.stream.IntStream;
      public class StreamApp {
           public static void main(String[] args) {
               IntStream.range(10, 60).forEach(System.out::println);
           }
      }
      

      结果:

      10
      11
      12
      .
      .
      .
      58
      59
      

      【讨论】:

        【解决方案16】:

        由于所有循环都需要条件语句,我们可以将问题简化为“列出不带条件的任意范围的数字”。在 java 中没有 boolean -> integer 转换,bools 只能用在条件中,所以我们可以把它从列表中划掉。

        这给我们留下了算术选项。我们可以用 1 和 0 伪造布尔值。要使用 1 或 0 代替真/假,我们可以创建一个包含 2 个方法的数组,第一个是我们的递归代码路径,另一个是我们的停止。所以我们只需要一个算法,计数为 0 时返回 1,任何非零值的计数返回 0。

        有很多东西可以将 0 与所有其他数字分开,但如果不除以零,就很难利用它。我利用的属性是 0 位于正数和负数之间。如果我们对整数集进行绝对化,则零是唯一在两边(1 和 1)具有相同数字的数字。知道了这一点,我们知道 abs(n-1/n+1) 对于 n=0 将为 1,而对于所有其他正数则为

        为了避免任何外部代码,我们可以将 abs(n) 替换为 n*n,因为 n 只能介于 -1 和 1 之间。就是这样,((a-1)/(a+1)) * ( (a-1)/(a+1)) 确实看起来很古怪,但它完美地满足了我们的需求。

        interface doMethod {
            void doIt(int start, int stop);
        }
        private static doMethod[] doList = new doMethod[] {
                new doMethod() { public void doIt(int start, int stop) { printNumbers(start, stop); } },
                new doMethod() { public void doIt(int start, int stop) {}}
        };
        public static void printNumbers(int start, int stop){
            System.out.println(start);
            //a is our 'count' variable
            int a = stop - start;
            //b is our 'index' variable
            int b = ((a-1)/(a+1)) * ((a-1)/(a+1));
            // doList[0 = recurse, 1 = stopRecursing]
            doList[b].doIt(start + 1, stop);
        }
        public static void main(String[] args) {
            printNumbers(10, 60);
        }
        

        【讨论】:

        • 我在这里闻到了 Prolog 和类似声明的味道。 :)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-10
        • 1970-01-01
        • 2011-02-06
        • 1970-01-01
        相关资源
        最近更新 更多