ホフスタッターHシーケンス


15

定義

  • a(0) = 0
  • a(n) = n-a(a(a(n-1))) 整数の n > 0

仕事

負でない整数を指定するとn、output a(n)

テストケース

n     a(n)
0     0
1     1
2     1
3     2
4     3
5     4
6     4
7     5
8     5
9     6
10    7
11    7
12    8
13    9
14    10
15    10
16    11
17    12
18    13
19    13
20    14
10000 6823

参照資料


ホフスタッターシーケンスに関する関連課題:123
マーティン・エンダー

4
そして、私はまだあなたがGEB ...参照すべきだと思う
マーティン・エンダー

1
お元気ですか 数論関連していますか?
flawr

1
@flawr facepalm もう一度試してみましょう:ゲーデル、エッシャー、バッハ:永遠の黄金編組
スティグ・ヘマー

1
@StigHemmerは実際に手のひらを顔に当てる今、独自の絵文字を持っています🤦
トビアスKienzler

回答:


20

Haskell、23 22バイト

f 0=0
f n=n-f(f$f$n-1)

単にシーケンスの定義を使用します。f(f$f$n-1)はと同等f (f (f (n-1)))です。

テスト:

main = putStrLn . show $ map f [0..20]
-- => [0,1,1,2,3,4,4,5,5,6,7,7,8,9,10,10,11,12,13,13,14]

おかげアンダースKaseorgます!


(f$f$f$n-1)= f(f$f$n-1)バイトを保存します。
アンダースカセオルグ

9

ゼリー、8 バイト

’ßßßạµṠ¡

オンラインでお試しください!または、より小さいテストケースを確認します。

使い方

’ßßßạµṠ¡  Main link. Argument: n

     µṠ¡  Execute the preceding chain sign(n) times.
’         Decrement n, yielding n - 1.
 ßßß      Recursively call the main link thrice.
    ạ     Take the absolute difference of n and the result.

9
Jellyパーサーは10バイトを超えるプログラムも処理できますか?
-steenbergh

9

Mathematica、20バイト

バイトカウントは、ISO 8859-1(または互換性のある)エンコードを想定し$CharacterEncoding、Windowsのデフォルトのような一致する値に設定されますWindowsANSI

±0=0
±n_:=n-±±±(n-1)

これは単項演算子を定義し±ます。


±が何をするのか、それがどのように機能するのかを説明してください。ところで、100kおめでとうございます。
DavidC

1
@DavidCありがとう。:)未使用のfunctionの省略形である組み込み演算子PlusMinusです。詳細については、この投稿を参照してください。
マーティンエンダー

1
とても興味深い。@または[ ]も分配します。
DavidC

9

J、14 12バイト

-$:^:3@<:^:*

@ Leaky Nunのおかげで2バイト節約

n -1でn > 0のときに3回それ自体を再帰的に呼び出し、その結果をnから減算することにより、結果を計算します。n = 0の場合、基本ケースには異なる状況があります。そこでは、0 に等しいn - nを計算します。

a(n) = n - n = 0           if n = 0
       n - a(a(a(n-1)))    if n > 0

ここで試してみてください。

説明

-$:^:3@<:^:*  Input: n
           *  Get the sign of n (n = 0 => 0, n > 0 => 1)
         ^:   Execute that many times
                (0 times means it will just be an identity function)
       <:       Decrement n
 $:             Call itself recursively
   ^:3          three times
      @         on n-1
-             Subtract that result from n and return

括弧は必要ないと思います。
リーキー修道女

6

ジュリア、16バイト

!n=n>0&&n-!!!~-n

オンラインでお試しください!

使い方

単項演算子を再定義します !ます。

もしn = 0で、比較n>0リターンとそう!

それ以外の場合、後のコード&&が実行されます。~-n(n-1)2の補数に相当し、n-1で3回!!!再帰的に呼び出し、結果の値がnから減算されます。!


説明を追加しますか?-!!~-._で何が起こっているのかわかりません。
ダウンゴート

1
派手なものは何もありません。!は単に関数の名前です。
デニス

5

Python、31バイト

a=lambda n:n and n-a(a(a(n-1)))

再帰制限と時間の制約により、上記の関数は実用的ではありませんが、理論的には機能するはずです(そして、小さなnでも機能します)。


4

JavaScript(ES6)、52バイト

n=>[0,...Array(n)].reduce((p,_,i,a)=>a[i]=i-a[a[p]])

私は退屈で再帰的なバージョンを書いたかもしれませんが、このバージョンははるかに高速で(最後のテストケースに簡単に対応できます)、使用するreduceのでプラスです!




3

R、42 41バイト

a=function(n)ifelse(n<1,0,n-a(a(a(n-1))))

使用法:

> a(1)
1
> a(10)
7

nただし、この再帰的なアプローチは、大きな値に対してはうまくスケーリングしません。


条件をに変更すると、1バイト(および不正な入力による多数のエラー)を失う可能性がありますn<1。シーケンスとして、それはとにかく非負の整数に対してのみ実際に定義されます。
user5957401

a=function(n)"if"(n,n-a(a(a(n-1))),0)数バイトオフで動作します。
ジュゼッペ


2

Sesos58 55バイト

0000000: 16e0d7 bdcdf8 8cdf1b e6cfbb 840d3f bf659b 38e187  ..............?.e.8..
0000015: f8639b 39dc37 fc893f 666c05 7e7ed9 b88b3f ae0d3f  .c.9.7..?fl.~~...?..?
000002a: 676ed8 bd9940 7fdc3b 36619e f1                    gn...@..;6a..

最大400の入力を処理します適切に処理しますが、それ以降は実行時間が劇的に増加します。

オンラインでお試しください!デバッグを確認をして、生成されたSBINコードを確認します。

Sesosアセンブリ

上記のバイナリファイルは、次のSASMコードをアセンブルして生成されています。

set numin, set numout

get
jmp
    jmp
        rwd 3, add 1, rwd 1, add 1, fwd 4, sub 1
    jnz
    rwd 3, sub 1
jnz
rwd 3, add 1, fwd 2
jmp
    rwd 1, sub 1, fwd 3, sub 1, fwd 2, add 3
    jmp
        rwd 2
        jmp
            rwd 3
        jnz
        fwd 6, get, rwd 4, sub 1
        jmp
            fwd 1, sub 1
            jmp
                rwd 3
            jnz
            sub 1
            jmp
                fwd 3
            jnz
            rwd 4, sub 1
        jnz
        fwd 1
        jmp
            rwd 1, add 1, fwd 1, add 1
        jnz
        sub 1, fwd 3, sub 1
        jmp
            fwd 3
        jnz
        rwd 1, sub 1
    jnz
    rwd 2, get
    nop
        rwd 3
    jnz
    fwd 3, get, rwd 2
    jmp
        fwd 2, add 1
        jmp
            fwd 3
        jnz
        rwd 1, add 1, rwd 2
        jmp
            rwd 3
        jnz
        fwd 1, sub 1
    jnz
    fwd 2
    jmp
        rwd 2, add 1, fwd 2, sub 1
    jnz
    nop
        get, fwd 3
    jnz
    rwd 1, add 1, fwd 2
jnz
rwd 2, sub 1
jmp
    rwd 1, sub 1, fwd 1, sub 1
jnz
rwd 1, put

2

LISP、61バイト

(defun H(N)(if(= N 0)(return-from H 0)(- N(H(H(H(- N 1)))))))

おそらく最適なソリューションではありませんが、機能します。


1

Java 7、42バイト

int c(int n){return n>0?n-c(c(c(n-1))):0;}

未ゴルフ&テストケース:

ここで試してみてください。

class Main{
  static int c(int n){
    return n > 0
              ? n - c(c(c(n-1)))
              : 0;
  }

  public static void main(String[] a){
    for(int i = 0; i < 21; i++){
      System.out.println(i + ": " + c(i));
    }
    System.out.println("1000: " + c(1000));
  }
}

出力:

0: 0
1: 1
2: 1
3: 2
4: 3
5: 4
6: 4
7: 5
8: 5
9: 6
10: 7
11: 7
12: 8
13: 9
14: 10
15: 10
16: 11
17: 12
18: 13
19: 13
20: 14
 (last case takes too long..)

1

ルビー、27バイト

明らかな実装。

a=->n{n<1?0:n-a[a[a[n-1]]]}

これは、シーケンス内の以前のエントリをキャッシュする、より長くて速い回答です。どちらの答えも1.9以降のバージョンでのみ機能します。それは->、スタビーなラムダがRubyに導入されたときでした。

->n{r=[0];i=0;(i+=1;r<<i-r[r[r[i-1]]])while i<n;r[n]}



1

C、 35 32バイト

@PeterTaylorのおかげで3バイト節約できました!

a(n){return n?n-a(a(a(n-1))):0;}

Ideoneでお試しください!


2
Cでは、3バイトの節約を与え、条件として直接整数を使用することができますa(n){return n?n-a(a(a(n-1))):0;}
ピーター・テイラー

1
@betseg - You have an erroneous : in your code too. You should take out the one after ?.
owacoder

1

Javascript ES6, 22 bytes

a=n=>n&&n-a(a(a(n-1)))

I'll be boring and do the recursive version :P


1

VBA, 69 bytes

Function H(N):ReDim G(N):For j=1To N:G(j)=j-G(G(G(j-1))):Next:H=G(N)

Works in the blink of an eye on the test set, slows down a little above n=1000000, runs into a memory wall a little above n=25 million.


1

Pyth, 10 bytes

L-WbbyFtb3

Defines a function y. Try it online: Demonstration

This uses a relative new feature of Pyth. You can apply a function multiple times using the fold-syntax. It doesn't actually save any bytes, I used it just for demonstration purposes.

Explanation:

L-WbbyFtb3
L            define function y(b), that returns:
    b           b
 -Wb            and subtract the following if b>0
     yF  3      y applied three times to
       tb       b - 1

1

Maple, 28 26 bytes

`if`(n=0,0,n-a(a(a(n-1))))

Usage:

> a:=n->ifelse(n=0,0,n-a(a(a(n-1))));
> seq(a(i),i=0..10);
0, 1, 1, 2, 3, 4, 4, 5, 5, 6, 7

1

dc, 34 bytes

dsn[zdddd1-;a;a;a-r:aln!=L]dsLx;ap

Input is taken from the top of the stack. This must be the only item on the stack, because the stack depth is used as a counter. Example of usage:

$ dc
10000dsn[zdddd1-;a;a;a-r:aln!=L]dsLx;ap

This is a fairly straightforward implementation of the sequence definition:

dsn               # Store n as `n', and keep a copy as a depth buffer (see below)
[                 # Open loop definition
 z                # Push stack depth i for i-th term
 dddd             # Duplicate stack depth four times, for a total of five copies
 1-               # Get i-1 for use as index to previous term
                  #   Note that if we hadn't duplicated n above, or left something else
                  #   on the stack, 0-1 would be -1, which is not a valid array index
 ;a;a;a           # Fetch a(a(a(i-1)))
 -                # Calculate i-a(a(a(i-1)))
 r                # Arrange stack to store i-th term: TOS |  i  (i-a(a(a(i-1))))
 :a               # Store i-th term in array `a'
 ln!=L            # Load n. If n!=i, we're not done calculating terms yet, so execute loop
]                 # Close loop definition. Note that we started with five copies of i:
                  #   i-1 was used to get last term
                  #   i-a(...) was used to calculate current term
                  #   ... i :a was used to store current term
                  #   i ln !=L was used to check loop exit condition
                  # One copy of i is left on the stack to increment counter
dsLx              # Duplicate loop macro, store it, and execute copy
;a                # Last i stored on stack from loop will equal n, so use this to get a(n)
p                 # Print a(n)

Anyways, it started out straightforward...then the golfing happened.



1

C++ ( MSVC, mainly )

Normal version : 40 bytes

int a(int n){return n?n-a(a(a(n-1))):0;}

Template meta programming version : 130 bytes

#define C {constexpr static int a(){return
template<int N>struct H C N-H<H<H<N-1>::a()>::a()>::a();}};template<>struct H<0>C 0;}};

Usage :

std::cout << a(20) << '\n';       // Normal version
std::cout << H<20>::a() << '\n';  // Template version

The template version is the fastest code, since there's nothing faster than moving a value into a register => with optimization, H<20>::a() compile as :

mov esi, 14

For 10000, the recursive version crashes due to a stack overflow error, and the template version crashes at compile time due to template instantiation depth. GCC goes to 900 ( 614 )


I think you don't need the space between C and { in the template meta programming version
Zacharý

@Zacharý MSVC refuses to compile without that space
HatsuPointerKun

Ahh, I see now why that seems to keep happening
Zacharý

@Zacharý It depends on the type of macro. If it has parameters, then i can remove the space, but here it doesn't
HatsuPointerKun


1

APL (Dyalog Unicode), 18 17 bytes

{⍵=0:0⋄⍵-∇⍣3⊢⍵-1}

Try it online!

Surprisingly, there's no APL answer to this challenge. This is a literal implementation of the function in the OP.

TIO times out for n>90.

Saved a byte thanks to @Zacharý.


1
{⍵=0:0⋄⍵-∇⍣3⊢⍵-1}
Zacharý


0

PowerShell v2+, 56 bytes

$a={$n=$args[0];if($n){$n-(&$a(&$a(&$a($n-1))))}else{0}}

The PowerShell equivalent of a lambda to form the recursive definition. Execute it via the & call operator, e.g. &$a(5). Takes a long time to execute -- even 50 on my machine (a recent i5 with 8GB RAM) takes around 90 seconds.

Faster iterative solution, 59 bytes

param($n)$o=,0;1..$n|%{$o+=$_-$o[$o[$o[$_-1]]]};$o[-1]*!!$n

Longer only because we need to account for input 0 (that's the *!!$n at the end). Otherwise we just iteratively construct the array up to $n, adding a new element each time, and output the last one at the end $o[-1]. Super-speedy -- calculating 10000 on my machine takes about 5 seconds.


0

><>, 55+2 = 57 bytes

^~n;
.~-]{:0$
v>1-}32[
v/  /:1-32[
>$:?/$~]{:0$.
/30@2[

The input is expected to be present on the stack at program start, so +2 bytes for the -v flag. Try it online!

This is hecka slow, as it uses recursion to calculate the result. Using TIO, h(50) takes over a minute. It returns the correct results <= 30, so I'm confident it would work for h(10000), I just haven't run it to find out!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.