仅使用* 3和/ 2运算将1转换为任何正整数


11

通过从1开始并应用一系列操作可获得任何正整数,每个操作要么是“乘以3”,要么是“除以2,则舍弃任何余数”

示例(用f表示* 3,用g表示/ 2):

4 = 1 *3 *3 /2 = 1 ffg
6 = 1 ffggf = 1 fffgg
21 = 1 fffgfgfgggf

编写一个具有以下行为的程序:

输入:通过stdin或硬编码的任何正整数。(如果是硬编码,则输入数字将从程序长度中排除。)
输出:一串f和g的字符串<input> = 1 <string>(例如示例中)。这样的反序字符串也是可以接受的。注意:输出仅包含f和g,或者为空。

当输入41时,获胜者是程序加输出字节最少的条目。


1
你怎么知道这是真的?
marinus 2013年

@marinus这被认为是正确的(但尚未得到证明)。寻找一些证据。
Fabinout

@marinus,您可以通过血统证明(或等效地通过强归纳法)是可能的。区分大小写x mod 3:如果x=3y构造y,然后应用f;如果x=3y+1构建2y+1和应用f,然后g; 如果x=3y+2这样,它会变得复杂,但本质上是递归的。
彼得·泰勒

另外,输出必须按应用顺序排列还是组成顺序也可以接受?
彼得·泰勒

@PeterTaylor两种方法都可以。
res

Answers:


3

GolfScript,得分64(43-2 + 23)

0{)1.$2base:s{{3*}{2/}if}/41=!}do;s{103^}%+

(41是硬编码的,因此得分为-2个字符)。输出是

fffgffggffggffgggffgggg

这是23个字符(没有换行符)。通过构造,代码保证了它总是返回最短的表示形式(之一)。


引用用户达伦·斯通建议编辑对这个职位:“我无法在这里发表评论,所以我会离开编辑此输出不包括前两个字符‘1’,也不是那些反映在分数应该是一个易于修复,但解决方案仍然非常短。干杯!” (我拒绝了,但以为我应该传达这个信息)
Doorknob

@Doorknob挑战指出"1 "不应在输出中包含。
霍华德

3

朋友们,我们越来越脏了!

爪哇 210207 199个字符

public class C{public static void main(String[] a){int i=41;String s="";while(i>1){if(i%3<1){s+="f";i/=3;}else if(i%3<2){s+="g";i+=i+1;}else{s+="g";i+=i+(Math.random()+0.5);}}System.out.println(s);}}

非高尔夫:

public class C {

    public static void main(String[] a) {

        int i = 41;
        String s = "";
        while (i > 1) {
            if (i % 3 == 0) {
                s += "f";
                i /= 3;
            } else {
                if (i % 3 == 1) {
                    s += "g";
                    i += i + 1;
                } else {
                    s += "g";
                    i += i + (Math.random() + 0.5);
                }
            }
        }
        System.out.println(s);
    }
}

输出:根据古老众神的信仰,我最短的时间是30岁。请注意,必须从右侧读取输出。

234

1 ggfgfgfgfggfggfgffgfggggfgffgfggfgfggggfgffgfggfgfggfgfggfgfgggggfffgfggfgfggfgfgggffgggggfffgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggfgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggggggggggggfgfgfggggfgfgfggfffgfgfggffgfgfggfgfggggffgfgfffff

108

1 gggffgfgfggggggfggggfgffggggfgfgfgfgfgffgggfgggggfggfffggfgfffffgggffggfgfgggffggfgfgggffggggggfgfgffgfgfff

编辑 45

1 ggfgfgfgfgggfggfffgfggfgfgggggggffgffgfgfff

要点: 318 199 + 30 = 229

编辑1(2 * i + 1)%3 == 0->(2 * i)%3 == 1

如果您在打高尔夫球时使用Java 6而不是Java 7,则可以使用

public class NoMain {
    static {
        //some code
        System.exit(1);
    }
}

39个字符的结构代替了53个字符长的标准结构。


(2*i+1)%3==0相当于i%3==1
Howard

是的。谢谢
Fabinout

if(X){A}else{if(Y){B}else{C}}比更长if(X){A}else if(Y){B}else{C}。您也可以==用较短的<条件代替条件。
彼得·泰勒

@PeterTaylor是的,我的解决方案仍然很难看。我不知道随机部分是否会使代码更短,但可以确保输出更糟糕。
Fabinout

您的f / g字符串以'g'开头(应该代表'/ 2'),因此它们会将1转换为0而不是41。将f改为g,反之亦然给41
水库

3

Python,得分124(90-2 + 36)

x=41;m=f=g=0
while(3**f!=x)*(m!=x):
 f+=1;m=3**f;g=0
 while m>x:m/=2;g+=1
print'f'*f+'g'*g

90个字符的字符(每个换行符为1个)-2个用于硬编码的输入数字+ 36个字符的输出

输出:

ffffffffffffffffgggggggggggggggggggg

1
如果这样做m=f=0,则可以使外部循环while(n!=x)*(m!=x)并删除中断。将其带入95个字符的代码中。
Daniel Lubarov

@丹尼尔:先生,您是一位绅士和学者。谢谢!您的提交仍然安全地领先于我10个字符。:)
达伦·斯通

1
您可以进一步节省一点,如果你更换所有n3**f
霍华德

1
对于input = 1,您的程序会生成错误(由于未进入外部while循环,因此未定义“名称'g'”)。
水库

1
你可以切出通过写作另一个字符print'f'*f+'g'*g,这将使得分为90-2 + 36 = 124
水库

3

Python,得分121(87-2 + 36)

t=bin(41)
l,n,f=len(t),1,0
while bin(n)[:l]!=t:f+=1;n*=3
print(len(bin(n))-l)*'g'+f*'f'

@Darren,我不确定如何解释输出描述,但是您可能是对的。我加了“ 1”。谢谢!
Daniel Lubarov

1
您可以再次删除“ 1”!您对输出描述的原始解释是正确的。再次享受Python带来的好处!:-)
达伦·斯通

1
如果您结合第2,第3,和第4行成l,n,f=len(t),1,0,并取消了'1',从打印语句,你的分数将是87-2 + 36 = 121
RES

谢谢大家-我放下了1,l,n,f=len(t),1,0给出相同数量的字符,对不对?(对于每个变量,an =和换行符都用两个,s 代替。)
Daniel Lubarov 2013年

如果每个换行符是一个字符(例如UNIX样式的LF),则单行和三行版本的长度相同。如果每个换行符是两个字符(例如,MS Windows样式的CR + LF),则单行版本比三行版本短两个字符。分数121假定一个字符的换行符。
res

1

Perl得分89(63-2 + 28)

$_=41;$_=${$g=$_%3||$_==21?g:f}?$_*2+$_%3%2:$_/3while$_>print$g

猜想:如果下面我的原始解决方案中描述的幼稚方法达到一个循环,则该循环将为 [21,7,15,15,5,10,21,...]。由于没有 1≤n≤10 6的反例,因此这似乎是正确的。为了证明这一点,就足以证明这是其中唯一的周期可以存在,这我可能会或可能不会在稍后的时间点做。

上述解决方案避免了立即循环,而不是(错误地)猜测,并且避免了第二次循环。

输出(28个字节):

ggfgfgfgfggfggfgfgfggfgfgfff

Perl,得分100(69-2 + 33)

$_=41;1while$_>print$s{$_=$$g?$_*2+$_%3%2:$_/3}=$g=$_%3||$s{$_/3}?g:f

使用猜测和检查的方法。字符串是使用反运算构造的(将值转换为1,而不是相反的方式),并且字符串会相应地进行镜像,这是问题说明所允许的。

每当遇到三的非整数倍时,它将乘以2,如果结果为三的整数倍,则将其相加。当遇到三的倍数时,它将除以三...除非先前已经遇到过该值,表示一个周期,因此是猜测。

输出(33字节):

ggfgfgfgfggfggfgffgfgggfggfgfgfff

1

J,得分103(82-2 + 23)

*注:我叫我的动词fg,不要与输出字符串混淆fg

硬编码:

f=:3 :'s=.1 for_a.y do.s=.((<.&-:)`(*&3)@.a)s end.'
'gf'{~#:(>:^:(41&~:@f@#:)^:_)1

通用功能:

f=:3 :'s=.1 for_a.y do.s=.((<.&-:)`(*&3)@.a)s end.'
g=:3 :'''gf''{~#:(>:^:(y&~:@f@#:)^:_)1'

取消了对二进制数字块的操作,这对压缩而言是最重要的更改g。重命名了变量,并删除了一些空格,但在功能上仍然相同。(用法:g 41

J,得分197(174 + 23)

f =: 3 : 0
acc =. 1
for_a. y do. acc =. ((*&3)`(<.&-:)@.a) acc end.
)

g =: 3 : 0
f2 =: f"1 f.
l =. 0$0
i =. 1
while. 0=$(l=.(#~(y&=@:f2))#:i.2^i) do. i=.>:i end.
'fg'{~{.l
)

输出: ffffffffggggggggfgffggg

f布尔值的列表转换成数,使用作为0 *3和1作为/2(和floor)。#:i.2^i创建一个包含所有长度为1的布尔型布尔数组的秩2数组i

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.