8应该成为无穷大[关闭]


19

让我们看一个典型的循环,该循环通常执行8次迭代:

for (int x=0; x<8; ++x);

您必须使其无限!


对于所有支持这种循环形式的语言,这都是一场for。因此,得分最高的解决方案(支持率减去支持率)将获胜。

如果您的语言有其他for循环形式,但是您可以肯定,可以用它来做些很酷的事情,可以随时发布答案并将其标记为不竞争。我保留扩大可用结构和语言范围的权利,但绝不会缩小,因此不要担心放弃以前正确的解决方案。


什么是解决方案?

解决方案由两个程序组成

第一个程序是干净程序。这是您语言中的典型程序,for循环进行8次迭代。它应该是普通程序,任何开发人员都可以编写。没有用于准备目的的任何特殊技巧。例如:

int main() 
{
  for (int x=0; x<8; ++x);
  return 0;
}

第二个程序被增强。该程序应包含干净程序中的所有代码以及一些其他代码。扩展点数量有限有关详细信息请参见完整规则部分。上面一个干净的增强程序可以是

inline bool operator < (const int &a, const int &b)
{
  return true;
}

int main() 
{
  for (int x=0; x<8; ++x);
  return 0;
}

那只是一个例子(在C ++中不可编译),以显示一个想法。真正正确的增强程序必须是可编译的,可运行的并且具有无限循环。

完整规则

两种程序:

  • 任何支持这种for循环的语言都是可以的。
  • 循环主体必须为空。更准确地说,您可以将一些输出或其他代码放入循环中,但是在空循环的情况下,循环行为应相同。

清洁程序:

  • 循环使用整数或数字计数器,并执行8次迭代:

    for (int          x=0; x<8; ++x);   // C, C++, C#
    for (var          x=0; x<8; ++x);   // C#, Javascript
    for (auto         x=0; x<8; ++x);   // C, C++
    for (auto signed  x=0; x<8; ++x);   // C, C++
    for (register int x=0; x<8; ++x);   // C, C++
    
  • 不允许使用用户定义的类型。

  • 不允许使用属性(全局变量除外)代替循环变量。
  • 变量的声明可以在循环内部或外部。可以使用以下代码:

    int x;
    for(x=0; x<8; ++x);
    
  • 可以使用前缀或后缀增量。

  • 循环限制8应写为常量文字,而不保存为命名常量或变量。这样做是为了防止基于声明等于8的变量或常量为基础的解决方案,然后通过其他值对其进行重新分配,覆盖或屏蔽:

    const double n = 8;
    
    int main()
    {
      const double n = 9007199254740992;
      for (double x=0; x<n; ++x);
      return 0;
    }
    

增强程序:

  • 必须包含干净代码中的所有代码。
  • 应该在有限数量的扩展点中扩展干净程序。
  • 必须执行 for无限循环本身相同的循环。
    将循环放置到另一个无限构造中是不可行的。
  • 只要代码的文本表示形式不变,就可以对代码进行运行时或编译时修补。
  • eval禁止将结构放入字符串中并传递给它。

扩展点:

  • 带有干净代码的片段之外的任何位置,包括其他文件或其他程序集。
  • for声明(作为单个部分- for结构及其主体)必须保持不变。
  • 变量声明必须保持相同。
  • 简单语句之间的任何位置都可以用作扩展点。
  • 当且仅当在循环外部声明了变量且没有立即分配值时,才可以添加这种分配。
/* extension point here */
int main()
/* extension point here */
{
  /* extension point here */
  int x /* extension point for assignment here */;
  /* extension point here */
  for (x=0; x<8; ++x);
  /* extension point here */
  return 0;
  /* extension point here */
}
/* extension point here */
int main() 
{
  /* BEGIN: No changes allowed */ int x = 0; /* END */
  /* extension point here */
  /* BEGIN: No changes allowed */ for (x=0; x<8; ++x); /* END */
  return 0;
}

PS:如果可能,请提供指向在线IDE的链接。


2
据我所知,@ Oliver是“最高分(最高投票数减去最低投票数)”的确切值,它是流行度竞赛的默认值,至少它写在标签说明中:“流行度竞赛是一项得分最高的答案的竞赛(加减减)获胜。” 但我可以将其明确添加到问题中。
Qwertiy

1
@Maltysen,通过这些构造,在语言方面有很多有趣的解决方案。有C和C ++(具有完全不同的解决方案),C#,Java,Javascript,php,Perl,Groovy。我敢肯定还有更多。无论如何,我愿意扩大问题,这是在规则中指定的。如果您可以用其他语言来做些有趣的事-请张贴。如果它将有积极的影响,可以扩大规则。
Qwertiy

4
将其作为受欢迎程度竞赛有点尴尬,因为没有描述选民在投票时应选择的标准(使胜利条件具有主观性)。我正在研究一个代码高尔夫球解决方案,其依据是许多人发现高尔夫解决方案很有趣,因此可能很流行。这似乎是挑战的可行胜利条件。

2
1.“ 整数或数字计数器 ”有点含糊。例如,其中包括java.lang.Integer?2.最好采用适当的获胜标准。
彼得·泰勒

1
1.是的。2.究竟是什么获胜标准?PS:我们可以继续meta
Qwertiy

Answers:


33

Python3

清洁程序:

这只是while循环的标准倒计时。

n = 8
while n != 0:
  n -= 1
print("done")

增强程序:

import ctypes

ctypes.cast(id(8), ctypes.POINTER(ctypes.c_int))[6] = 9

n = 8
while n != 0:
  n -= 1
print("done")

它使用INT缓存重新定义89有效地使n -= 1无操作,因为9-1 = 8这只是设置n9再次引起无限循环。

您可以在此处在线查看int缓存的运行情况 (尽管很明显,在线时没有死循环)。


您能否提供指向onlinde IDE的链接?ideone.com/aI3ZrI-似乎无法正常运行。
Qwertiy

@Qwertiy,我尝试在repl.it中运行它,但是它只是冻结了,这是可以预期的,因为它将是一个无限循环。我知道INT缓存的东西在那里工作,因为这是我如何设置实验89
Maltysen

真的在那里工作。奇怪的是,这些东西没有像ideone那样的时间限制(5秒)。他们显示Python 3.5.2 (default, Dec 2015, 13:05:11) [GCC 4.8.2] on linux
Qwertiy

@Qwertiy链接不带循环:repl.it/E4fx/0
Maltysen,2016年

这很有趣……
Qwertiy

22

Python 3

清洁程序:

在python中执行8次操作的标准方法是:

for i in range(8): 
    # Do something
    pass

增强程序:

但是,如果我们覆盖范围生成器函数以无限产生1,则它将变成无限循环...

def range(x):
    while 1: yield 1

for i in range(8):
    # Infinite loop
    pass

我们可以更进一步,创建一个生成器函数,而不是无限地产生1,永远计数:

def range(x):
    i = 0
    while 1: yield i; i+=1

for i in range(8):
    # Counting from 0 to infinity
    pass

在repl.it上测试


2
隐藏在一个巨大的模块中间...
本杰明

21

佩尔

清洁

for($i=0; $i<8; $i++) { }

增强型

*i=*|;
for($i=0; $i<8; $i++) { }

伊迪奥


16
哦,那真的很聪明。对于不了解Perl的任何人:这是别名$i,它成为仅能容纳布尔值的特殊变量的别名,因此,一旦其达到1,它就不会被增加。

10

ES5 +(JavaScript)

编辑:删除了显式变量声明,否则它被吊起并且创建了不可配置的window.x属性(除非在REPL控制台中逐行运行)。

说明:

利用以下事实:任何全局范围的变量也是window对象的属性,并将“ window.x”属性重新定义为具有恒定值1。

清洁

for(x=0; x<8; x+=1) console.log(x);

增强型

Object.defineProperty(window,'x',{value:1});
for(x=0; x<8; x+=1) console.log(x);

注意:要在Node.js中实现此功能,只需将“ window”替换为“ global”(在Node.js 6.8.0中进行了测试)


1
顺便说一下,是ES5,不是吗?
Qwertiy

而且它var在Crome中不起作用。但是您可以var从这两个程序中删除-可以。
Qwertiy

@Qwertiy对于我来说,这确实适用于Chrome中的“ var”(Linux /版本52.0.2743.82(64位))
zeppelin

>顺便说一下,是ES5,不是吗?是的,请立即更正标题
zeppelin

1
问题是var葫芦,所以在使用时defineProperty它已经退出了。但是,如果将这两行放在不同的脚本中(顺便说一句,是允许的),它将起作用,因为将首先创建该属性,var然后将忽略该属性。证明:i.stack.imgur.com/lSwbE.png
Qwertiy

10

C

清洁程序

int main() 
{
  for (int x=0; x<8; ++x);
  return 0;
}

增强程序

#define for(ever) while(1)

int main() 
{
  for (int x=0; x<8; ++x);
  return 0;
}

Must execute same for loop as an infinite loop itself. Placing of the loop into another infinite construction is not ok.
Karl Napf

3
@KarlNapf“ for”循环不在另一个无限构造中。
coredump

3
@KarlNapf我认为该答案已被规则明确允许:•只要代码的文本表示形式不变,就可以对代码进行运行时或编译时修补。
奥马尔

它的措词是“必须为循环执行相同”,但是是的,这与文本表示法冲突。
Karl Napf '16

7

爪哇

清洁程序:

public class Main {
    public static void main(String[] args) throws Exception {
        for (Integer i = 0; i < 8; i++);
    }
}

增强程序:

import java.lang.reflect.Field;

public class Main {
    public static void main(String[] args) throws Exception {
        Class cache = Integer.class.getDeclaredClasses()[0];
        Field c = cache.getDeclaredField("cache");
        c.setAccessible(true);
        Integer[] intcache = (Integer[]) c.get(cache);
        intcache[129] = intcache[128];

        for (Integer i = 0; i < 8; i++);
    }
}

将应该包含1的Integer高速缓存中的Integer设置为0,实际上i++什么也不做(它设置i为应该包含1的高速缓存Integer,但是由于该Integer实际上包含0,所以没有任何变化)。


击败我吧,此解决方案与我自己的解决方案相同。
Hypino

6
这实际上不是惯用的Java for循环,可能会使用未装箱的int而不是相对重量级的Integer


6

Python 3(3.5.0)

清洁程序:

for i in range(8):
    print(i)

增强型

import sys

from ctypes import *

code = sys._getframe().f_code.co_code

cast(sys._getframe().f_code.co_code, POINTER(c_char*len(code))).contents[len(code)-4] = 113
cast(sys._getframe().f_code.co_code, POINTER(c_char*len(code))).contents[len(code)-3] = 160

for i in range(8):
    print(i)

该解决方案与其他用Python编写的解决方案不同,它实际上可以即时更改源代码。for循环中的所有内容都可以更改为所需的任何代码。

该代码将倒数第二个操作码更改为113-或更可读JUMP_ABSOLUTE。它将操作数更改为-for 160循环开始的指令,实际上在程序末尾创建了GOTO语句。

增强程序会0..7无数次打印数字,而不会导致堆栈溢出或类似情况。


6

的PHP

我认为这是遵循扩展点规则的;关于第4点,我还不太清楚,它与@primo的perl答案非常相似,因此我认为它很重要。

清洁

for(;$i<8;$i++);

增强型

$i='a';
for(;$i<8;$i++);

PHP使您可以增加某些字符串,如下所示:

'a' -> 'b'
'b' -> 'c'
'z' -> 'aa'
'aa' -> 'ab'
'aab' -> 'aac'
etc

所有这些字符串的计算结果均为0,因此它将几乎永远循环(除非以某种方式耗尽内存)。


这是竞争的精神,而且非常有趣。实际上,关于忽略初始的assignmnet并没有说什么,所以这是一个极端的情况。实际上,预期在分配0和迭代之间没有扩展点。但是我现在不会禁止它,因为我看到了一些基于此的有趣的案例,而且不容易过度使用。
Qwertiy

2
@Qwertiy“这就是一些极端情况。” 简而言之,PHP :)
ToXik-yogHurt,2016年

6

佩尔

干净的代码

for ($x = 0; $x < 8; $x++) {}

增强码

sub TIESCALAR {bless []}
sub FETCH {}
sub STORE {}
tie $x, "";

for ($x = 0; $x < 8; $x++) {}

大多数Perl变量只是变量。但是,该语言还具有一项tie功能,可让您有效地提供变量的获取器和设置器。在此程序中,我将主程序包(其名称为空字符串)制作成等同于面向对象语言的类,同时还使其成为程序。这使我可以将for循环计数器与程序本身联系起来。实施TIESCALAR可以tie成功;的返回值TIESCALAR旨在作为对我们需要与该变量关联的任何内部状态的引用,但是由于我们不需要任何内部状态,因此我们返回一个空数组引用作为占位符。然后,我们给出getter和setter的最简单的实现。他们都不做任何事情,因此尝试分配给$x无效,尝试读取它总是会返回undef,其数值小于8。


5

WinDbg

清洁

.for (r$t0 = 0; @$t0 < 8; r$t0 = @$t0 + 1) { }

增强型

aS < |;                                            * Create alias of < as |
.block {                                           * Explicit block so aliases are expanded
    .for (r$t0 = 0; @$t0 < 8; r$t0 = @$t0 + 1) { } * Condition is now @$t0 | 8, always true
}

这种方法为<as 创建别名|,因此<在代码中遇到别名时,别名会扩展为|按位或,而不是小于。在WinDbg中,所有非零值都是真实的,因此anything | 8总是如此。

注意:.block如果aS.for实际以两条不同的行输入(如此处所示),则实际上并不需要,仅当aS.for处于同一行时才需要。


5

Mathematica

清洁

For[x = 0, x < 8, ++x,]

增强型

x /: (x = 0) := x = -Infinity;
For[x = 0, x < 8, ++x,]

5

普通口齿不清

干净的代码

(dotimes(i 8))

增强型

(shadowing-import(defmacro :dotimes(&rest args)'(loop)))
(dotimes(i 8))

定义了一个名为keyword:dotimesaka 的宏:dotimes(请参见11.1.2.3 KEYWORD Package),该宏将扩展为无限循环。所述defmacro所定义的宏的名称宏返回,其可以被进料至shadowing-import。因此,此新dotimes符号遮盖了标准符号(不应在可移植程序中对其进行重新定义或用词法绑定到另一个宏)。

增强型(2)

(set-macro-character #\8 (lambda (&rest args) '(loop)))
(dotimes(i 8))

读取字符8时,将其替换为(loop)。这意味着上面(dotimes (i (loop)))的代码读为,因此代码永远不会终止计算上限。这会影响所有出现的8,不仅影响循环中的一个。 换句话说,8实际上代表无穷大。 如果您很好奇,当对readtable进行如上修改时,字符8变为“终止”,并将其与当前正在读取的其他数字/符号分离:

(list 6789)

...读为:

(list 67 (loop) 9)

您可以在Ideone上运行测试:https ://ideone.com/sR3AiU 。


4

红宝石

清洁

这种for循环在Ruby中使用不多,但是一个典型的教程将告诉您这是解决问题的方法:

for x in 1..8
  # Some code here
end

增强型

for循环仅(1..8).each使用给定的代码块进行调用,因此我们更改了该方法:

class Range
  def each
    i = first
    loop { yield i; i+= 1 }
  end
end

for x in 1..8
  # Some code here
end

4

哈斯克尔

干净版本:

import Control.Monad (forM_)

main = forM_ [0..8] $ \i -> print i

增强版:

import Control.Monad (forM_)

data T = C

instance Num T where
    fromInteger _ = C

instance Enum T where
    enumFromTo _ _ = repeat C

instance Show T where
    show _ = "0"

default (T)

main = forM_ [0..8] $ \i -> print i

实际上,这是非常基本的:我们只是定义自己的类型T,使其enumFromTo实例为无限序列,然后使用类型默认设置,以便将未类型注释的值08视为type T


1
更改Haskell重载数字文字的默认类型的好主意。
nimi 2016年

3

///

for/// 中没有显式循环,但是可以模拟(毕竟它已经完成了)。

清洁:

/1/0/
/2/1/
/3/2/
/4/3/
/5/4/
/6/5/
/7/6/
/8/7/
8

增强:

/0/0/
/1/0/
/2/1/
/3/2/
/4/3/
/5/4/
/6/5/
/7/6/
/8/7/
8

这是怎么回事?

前者的程序从8倒数到0,而后者的/0/0/规则将替换00直到永恒。


我认为您实际上会做一些喜欢/0/1//1/2/.../7/8//8/8/8算数的事情。
暴民埃里克(Erik the Outgolfer)

3

Javascript ES6

OK,这是一个使用ES6 for ... of循环构造的版本。我什至会给您一个干净的阵列,以便我们确定没有什么可笑的事情:

清洁

for(a of [0,1,2,3,4,5,6,7]);

当然,这并不能阻止某人弄乱Array原型...

增强型

Array.prototype[Symbol.iterator]=function(){return {next: function(){return {done: false}}}}
for(a of [0,1,2,3,4,5,6,7]);

通过覆盖默认迭代器以使其永不终止,从而将所有内容锁定为无限循环来工作。该代码甚至没有机会在循环内运行这些东西。


“在空循环的情况下,循环行为应相同”
Qwertiy

达恩(Darn),想念那个-我得弄清楚点。
马库斯·迪尔

据我所知,除非违反规则,否则不可能在Javascript中使用C样式的for循环来应对挑战-通过在其中包含某些内容(例如我的解决方案)或预先按摩循环干净代码中的声明(例如Cedric Reichenbach的声明)。
Marcus Dirr

实际上有一些方法。具有全局变量的方法已经发布,但是还有更多,允许var循环。
Qwertiy

就像我说的,据我所知。发表评论后,我看到了全局变量的方式,并踢了自己。
Marcus Dirr,2016年

2

C ++

使用2个扩展点:

struct True {
  True(int x){}
  bool operator<(const int&){
    return true;
  }
  void operator++(){}
};


int main() 
{
#define int True
  for (int x=0; x<8; ++x);
  return 0;
}

清理程序与描述中的相同。


很好,但是可以“优化” :) C ++中有一些有趣的内置函数可以提供另一个答案。
Qwertiy

2

脑干

我将每个迭代打印为“ 0”,只是为了便于计算迭代次数。但是,可以在不更改循环工作原理的情况下将任何代码插入此处。

清洁

>> ++++++ [-<++++++++>] <<                   b = '0' (value to be printed each iteration)

>> ++++++++ [-<< ++++++++ ++++++++ >>] <<    for (a = a plus 128;
[                                              a;
++++++++ ++++++++                              a = a plus 16 (mod 256)) {
>.<                                              loop body (print b)
]                                            }

在线尝试

增强版本依赖于具有8位单元的常见Brainfuck实现。在这些实现中,“增量”实际上是“增量(mod 256)”。因此,要找到一个循环,在干净版本中将精确地循环8次,而在增强版本中将无限循环,我们可以简单地找到以下不等式系统的解决方案。

  • a + b * 8(mod 256)== 0(用于纯净版本)
  • 对于所有n,c + a + b * n(mod 256)> 0(用于增强版本)
  • > 0

在这种情况下,我们让a = 128,b = 16和c =1。显然,128 + 16 * 8 = 256(和256(mod 256)= 0)并且128> 0,并且由于b为偶数,因此c + a + b * n对于任何奇数a + c都是奇数,因此在这种情况下永远不会是256的偶数倍。为了简单起见,我们选择c = 1。因此,我们唯一需要的更改是+在程序开始时进行一个更改。

增强型

+                                            increment a (only change)
>> ++++++ [-<++++++++>] <<                   b = '0' (value to be printed each iteration)

>> ++++++++ [-<< ++++++++ ++++++++ >>] <<    for (a = a plus 128;
[                                              a;
++++++++ ++++++++                              a = a plus 16 (mod 256)) {
>.<                                              loop body (print b)
]                                            }

在线尝试

我将其留给OP以确定此条目是否竞争。Brainfuck没有明确的for循环,但是我使用的循环形式与您可能会得到的接近。 ++++++++也尽可能接近字面量8;我已经包括了很多。

干净的版本几乎可以肯定是用这种语言编写的典型程序,因为即使是最短的已知Brainfuck Hello World也依赖于工作的模块化递归关系。


2

哈斯克尔

清洁

import Control.Monad (forM_)

main = forM_ [0..8] $ \i -> print i

增强型

import Control.Monad (forM_)

import Prelude hiding (($))
import Control.Monad (when)

f $ x = f (\i -> x i >> when (i == 8) (f $ x))

main = forM_ [0..8] $ \i -> print i

用通常$在每次结束时再次重复循环的函数应用程序运算符替换。运行干净版本会打印0到8,然后停止;增强版打印0到8,然后再次打印0到8,依此类推。

我有点作弊,因为这forM_ [0..8] $ \i -> print i不一定是在Haskell中编写该循环的“最干净”的方式。许多Haskellers都会对循环体进行eta缩减forM_ [0..8] print,然后再没有其他方法$可以覆盖。在我的辩护中,我复制了不需要该属性的Cactus答案中的原始代码,因此至少一个Haskell程序员实际上编写该代码时没有动机不必要地添加$!!


1

C ++

int main() 
{
  int y;
#define int
#define x (y=7)
  for (int x=0; x<8; ++x);
  return 0;
}

让我们x求值为7。在C语言中不起作用,因为它在赋值和递增时需要一个左值。


1

尼姆

惯用的版本,使用countup

清洁

for i in countup(1, 8):
  # counting from 1 to 8, inclusive
  discard

增强型

iterator countup(a: int, b: int): int =
  while true:
    yield 8

for i in countup(1, 8):
  # counting 8s forever
  discard

简单,非常类似于重新定义的Python答案range。我们重新定义countup了惯用的Nim从一个int(含)迭代到另一个int的方式,以无限地给出8s。

使用range运算符的更有趣的版本..

清洁

for i in 1..8:
  # counting from 1 to 8, inclusive
  discard

增强型

iterator `..`(a: int, b: int): int =
  while true:
    yield 8

for i in 1..8:
  # counting 8s forever
  discard

与之前的解决方案非常相似,除了我们重新定义了range运算符..(通常会[1, 2, 3, 4, 5, 6, 7, 8]从之前为迭代器提供一个array)。


1

高尔夫脚本

清洁

0{.8<}{)}while;

增强型

{.)}:8;
0{.8<}{)}while;

它将返回n + 1的函数分配给变量8


1

tcl

正常:

for {set i 0} {$i<8} {incr i} {}

增强:

proc incr x {}
for {set i 0} {$i<8} {incr i} {}

这个想法是重新定义incr用于增加变量的命令i实际上不递增!

可以在以下位置进行测试:http : //rextester.com/live/QSKZPQ49822


1

x86_64组装

清洁程序:

mov rcx, 8
loop_start:
sub rcx, 1
cmp rcx,0
jne loop_start
mov rax, 0x01
mov rdi, 0
syscall

任何Assembly程序员都会使用的那种循环,然后退出syscall,以免jmp loop_start以后再添加指令。

增强程序:

global start
section .text
start:
mov rcx, -1
jmp loop_start
mov rcx, 8
loop_start:
sub rcx, 1
cmp rcx,0
jne loop_start
mov rax, 0x01
mov rdi, 0
syscall

另外,如果清理程序没有入口点或 section .text


整数溢出后会停止吗?
Qwertiy

1
哦,也许。但是需要很长时间吗?我有点忘了那种可能会发生的情况,因为他主要是高级语言程序员
goose121 '17


0

C ++

清洁程序

一个不错的普通循环,从数字0到7进行迭代。

#include <iostream>

int main() {

  for (short i = 0; i < 8; i++) {
    // Print `i` with a newline.
    std::cout << i << std::endl;
  }    

}

增强程序

C ++的预处理器是一个非常危险的功能...

#include <iostream>
#define short bool

int main() {

  for (short i = 0; i < 8; i++) {
    // Print `i` with a newline.
    std::cout << i << std::endl;
  }    

}

我们必须添加的唯一一行是#define short bool。这将生成i一个布尔值而不是一个短整数,因此,增量运算符(i++)在i达到1 后不执行任何操作。输出如下所示:

0
1个
1个
1个
1个
1个
...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.