Olumlu gerekçeleri numaralayın


14

Pozitif rasyonel sayıların aşağıdaki işlemle sayılabileceği gösterilebilir:

  1. Sıfıra göre sıra sayısı 0
  2. Bir ızgaradaki diğer sayıları, satır a, sütun b / a içerecek şekilde düzenleyin
  3. Sağ üstten sola çapraz zikzak çizin
  4. Zig-zag boyunca karşılaşılan benzersiz sayıları takip edin

İşte zig-zag'ın bir resmi:

1/1'de başlayın, ilk hareket sağa

Yani, karşılaşılan sayılar sırasıyla

1/1, 2/1, 1/2, 1/3, 2/2, 3/1, 4/1, 3/2, 2/3, 1/4, 1/5, 2/4, 3/3, 4/2, 5/1, 6/1, 5/2, 4/3, 3/4, 2/5, 1/6, 1/7, 2/6, 3/5, 4/4, 5/3 ...

Karşılaşılan basitleştirilmiş, benzersiz sayılar

1, 2, 1/2, 1/3, 3, 4, 3/2, 2/3, 1/4, 1/5, 5, 6, 5/2, 4/3, 3/4, 2/5, 1/6, 1/7, 3/5, 5/3, ...

Meydan okuma:

  • Verilen iki daha büyük, sıfır tamsayı p ve q , çıkış sıra sayısı p / q
  • p ve q zorunlu olarak eş-birincil değildir
  • En kısa kod kazanır
  • Standart boşluklar yasaktır

Test senaryoları:

Karşılaşılan ilk 24 rasyonel sayı ve her biri için istenen çıktı:

1/1: 1
2/1: 2
1/2: 3
1/3: 4
2/2: 1
3/1: 5
4/1: 6
3/2: 7
2/3: 8
1/4: 9
1/5: 10
2/4: 3
3/3: 1
4/2: 2
5/1: 11
6/1: 12
5/2: 13
4/3: 14
3/4: 15
2/5: 16
1/6: 17
1/7: 18
2/6: 4
3/5: 19

Ve daha sonraki test durumları için, sırasıyla 200 ilk pozitif rasyonel sayı:

1, 2, 1/2, 1/3, 3, 4, 3/2, 2/3, 1/4, 1/5, 
5, 6, 5/2, 4/3, 3/4, 2/5, 1/6, 1/7, 3/5, 5/3, 
7, 8, 7/2, 5/4, 4/5, 2/7, 1/8, 1/9, 3/7, 7/3, 
9, 10, 9/2, 8/3, 7/4, 6/5, 5/6, 4/7, 3/8, 2/9, 
1/10, 1/11, 5/7, 7/5, 11, 12, 11/2, 10/3, 9/4, 8/5, 
7/6, 6/7, 5/8, 4/9, 3/10, 2/11, 1/12, 1/13, 3/11, 5/9, 
9/5, 11/3, 13, 14, 13/2, 11/4, 8/7, 7/8, 4/11, 2/13, 
1/14, 1/15, 3/13, 5/11, 7/9, 9/7, 11/5, 13/3, 15, 16, 
15/2, 14/3, 13/4, 12/5, 11/6, 10/7, 9/8, 8/9, 7/10, 6/11, 
5/12, 4/13, 3/14, 2/15, 1/16, 1/17, 5/13, 7/11, 11/7, 13/5, 
17, 18, 17/2, 16/3, 15/4, 14/5, 13/6, 12/7, 11/8, 10/9, 
9/10, 8/11, 7/12, 6/13, 5/14, 4/15, 3/16, 2/17, 1/18, 1/19, 
3/17, 7/13, 9/11, 11/9, 13/7, 17/3, 19, 20, 19/2, 17/4, 
16/5, 13/8, 11/10, 10/11, 8/13, 5/16, 4/17, 2/19, 1/20, 1/21, 
3/19, 5/17, 7/15, 9/13, 13/9, 15/7, 17/5, 19/3, 21, 22, 
21/2, 20/3, 19/4, 18/5, 17/6, 16/7, 15/8, 14/9, 13/10, 12/11, 
11/12, 10/13, 9/14, 8/15, 7/16, 6/17, 5/18, 4/19, 3/20, 2/21, 
1/22, 1/23, 5/19, 7/17, 11/13, 13/11, 17/7, 19/5, 23, 24, 
23/2, 22/3, 21/4, 19/6, 18/7, 17/8, 16/9, 14/11, 13/12, 12/13, 
11/14, 9/16, 8/17, 7/18, 6/19, 4/21, 3/22, 2/23, 1/24, 1/25 

Ek test senaryoları oluşturmak için cevapları kullanamayacağınız ilk hamlenin aşağı olduğu ters soruya seslenin .


Kısa kod için alternatif numaralandırma şemaları olup olmadığını merak ediyorum.
qwr

1
Kesirlerin sayıları : oeis.org/A157807 paydaları: oeis.org/A157813 Sıra sıralaması için eşleşme yok: oeis.org/…
qwr

anlıyorum. kesri azaltmak ve sonra saymak zorunda. bu sadece zig-zag
değil

Yanıtlar:


4

Jöle ,  21  20 bayt

Muhtemelen akıllı bir matematik kullanarak birkaç bayt tarafından yenilebilir ...

:g/
ǵSRRUĖ€UÐeẎÇ€Qi

Listesini kabul eden [p,q]ve atanan doğal sayıyı döndüren monadik bir bağlantı p/q.

Çevrimiçi deneyin! Veya test takımına bakın .

Nasıl?

Dikkatinizi çekeriz N inci diyagonal karşılaştı pay ve payda toplamı eşittir hangi ızgaranın rasyonel sayılar tümünü içeren N + 1 , yani bir azaltan bir işlev verilmiş [p,q]en basit forma çifti ( [p/gcd(p,q),q/gcd(p,q)]) biz uzakta gibi diyagonallerini inşa edebilirsiniz * olmalıdır, tüm girdileri azaltın, çoğaltmayı kaldırın ve basitleştirilmiş girdinin dizinini bulun.

* aslında bir bayt kurtarmak için burada bir tane daha

:g/ - Link 1, simplify a pair: list of integers, [a, b]
  / - reduce using:
 g  - Greatest Common Divisor -> gcd(a, b)
:   - integer division (vectorises) -> [a/gcd(a,b), b/gcd(a,b)]

ǵSRRUĖ€UÐeẎÇ€Qi - Main Link: list of integers, [p, q]
Ç                - call last Link as a monad (simplify)
 µ               - start a new monadic chain (call that V)
  S              - sum -> the diagonal V will be in plus one
   R             - range -> [1,2,3,...,diag(V)+1]
    R            - range (vectorises) -> [[1],[1,2],[1,2,3],...,[1,2,3,...,diag(V)+1]]
     U           - reverse each       -> [[1],[2,1],[3,2,1],[diag(V)+1,...,3,2,1]]
      Ė€         - enumerate €ach     -> [[[1,1]],[[1,2],[2,1]],[[1,3],[2,2],[3,1]],[[1,diag(V)+1],...,[diag(V)-1,3],[diag(V),2],[diag(V)+1,1]]]
         Ðe      - apply only to the even indexed items:
        U        -   reverse each     -> [[[1,1]],[[2,1],[1,2]],[[1,3],[2,2],[3,1]],[[4,1],[3,2],[2,3],[1,4]],...]
           Ẏ     - tighten            -> [[1,1],[2,1],[1,2],[1,3],[2,2],[3,1],[4,1],[3,2],[2,3],[1,4],...]
            Ç€   - for €ach: call last Link as a monad (simplify each)
                 -                    -> [[1,1],[2,1],[1,2],[1,3],[1,1],[3,1],[4,1],[3,2],[2,3],[1,4],...]
              Q  - de-duplicate       -> [[1,1],[2,1],[1,2],[1,3],[3,1],[4,1],[3,2],[2,3],[1,4],...]
               i - index of V in that list

3

Perl 6 ,  94  90 bayt

->\p,\q{(({|(1…($+=2)…1)}…*)Z/(1,{|(1…(($||=1)+=2)…1)}…*)).unique.first(p/q,:k)+1}

Dene

{(({|(1…($+=2)…1)}…*)Z/(1,{|(1…(($||=1)+=2)…1)}…*)).unique.first($^p/$^q):k+1}

Dene

Bu temelde tüm değerler dizisini oluşturur ve bir eşleşme bulduğunda durur.

Expanded:

{  # bare block lambda with placeholder parameters $p,$q

  (
      ( # sequence of numerators

        {
          |( # slip into outer sequence (flatten)

            1      # start at one
            
            (
              $    # state variable
              += 2 # increment it by two each time this block is called
            )
            
            1      # finish at one
          )

        }
         * # never stop generating values
      )


    Z/   # zip using &infix:« /  » (generates Rats)


      ( # sequence of denominators

        1,  # start with an extra one

        {
          |( # slip into outer sequence (flatten)

            1
            
            (
              ( $ ||= 1 ) # state variable that starts with 1 (rather than 0)
              += 2        # increment it by two each time this is called
            )
            
            1
          )
        }
         * # never stop generating values
      )


  ).unique            # get only the unique values
  .first( $^p / $^q ) # find the first one that matches the input
  :k                  # get the index instead (0 based)
  + 1                 # add one               (1 based)
}

({1…($+=2)…1}…*)sonsuz sayı dizisi üretir ( |(…)düzleştirmek için yukarıda kullanılır)

(1 2 1)
(1 2 3 4 3 2 1)
(1 2 3 4 5 6 5 4 3 2 1)
(1 2 3 4 5 6 7 8 7 6 5 4 3 2 1)
(1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1)

(1,{1…(($||=1)+=2)…1}…*) sonsuz payda dizisi üretir

1
(1 2 3 2 1)
(1 2 3 4 5 4 3 2 1)
(1 2 3 4 5 6 7 6 5 4 3 2 1)
(1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1)
(1 2 3 4 5 6 7 8 9 10 11 10 9 8 7 6 5 4 3 2 1)

3

Python 2 , 157 144 137 134 126 125 bayt

def f(p,q):a=[((j-i)/(i+1.))**(j%-2|1)for j in range(p-~q)for i in range(j)];return-~sorted(set(a),key=a.index).index(p*1./q)

Çevrimiçi deneyin!

Bay Xcoder nedeniyle 4 bayt tasarruf etti ; Jonathon Frech'den 1 bayt .

Bay Xcoder tarafından belirtildiği gibi, Python 3'te biraz daha iyi yapabiliriz, çünkü diğer şeylerin yanı sıra, tamsayı bölümü varsayılan olarak yüzer sonuçları kullanır ve lists:

Python 3 , 117 bayt

def f(p,q):a=[((j-i)/-~i)**(j%-2|1)for j in range(p-~q)for i in range(j)];return-~sorted({*a},key=a.index).index(p/q)

Çevrimiçi deneyin!


128 bayt (-6) kısmını değiştirmeyi ve kullanarak **(j%-2|1)ve p-~q.
Bay Xcoder

@Bay. Xcoder: Bugün tamamen negatif modulo hakkındasınız! :) Sanırım hala +1sonunda ihtiyacım var , çünkü 1,1'zorunluluk' vermek 1, değil 0.
Chas Brown


124 bytes :) Evet, negatif modulo gerçekten yardımcı oluyor!
Bay Xcoder


3

Python 3 ,157, 146, 140133 bayt

def f(p,q):a=[(i+i-abs(j-i-i))/(abs(j-i-i+.5)+.5)for i in range(p+q)for j in range(4*i)];return sorted(set(a),key=a.index).index(p/q)

Çevrimiçi deneyin!

Jonathan Frech sayesinde 11 bayt kazandı

6 bayt daha ve sonra 7 Chas Brown sayesinde




@bobrobbob: PPCG'ye hoş geldiniz! Algoritmanızın nasıl çalıştığından emin değilim (açıkça çalışmasına rağmen); ancak deneysel olarak, değiştirerek biraz daha bayt kaydedebilirsiniz görünüyor range(max(p,q)+1)ile range(p+q).
Chas Brown

1
Sen kullanarak biraz daha bayt kaydedebilirsiniz {*a}yerine set(a).
Bay Xcoder

2

J, 41 , 35 , 30 bayt

FrownyFrog sayesinde -11 bayt

%i.~0~.@,@,[:]`|./.[:%/~1+i.@*

Çevrimiçi deneyin!

açıklama ile orijinal 41 bayt sonrası

%>:@i.~[:([:~.@;[:<@|.`</.%"1 0)~(1+i.@*)

ungolfed

% >:@i.~ [: ([: ~.@; [: <@|.`</. %"1 0)~ 1 + i.@*

açıklama

                  +
                  | Everything to the right of this
                  | calculates the list
p (left arg)      |                                      create the
divided by q      |                                      diagonals.  yes,
      (right)     |                                     +this is a         +create this list
   |              |        ++ finally rmv ^alternately  |primitive ADVERB  |1..(p*q), and pass
   |   + the index          | the boxes,  |box, or      |in J              |it as both the left
   |   | of that  |         | and remove  |reverse and  |                  |and right arg to the
   |   | in the   |         | any dups    |box, each    |                  |middle verb, where each
   |   | list on  |         |             |diagonal     |                  |element will divide the
   |   | the right|         |             |             |       +----------+entire list, producing
   |   | plus 1   |         |             |             |       |          |the undiagonalized grid
   |   |          |         |             |             |       |          |
   |   |          |         |             |             |       |          |
   |   |          +         |             |             |       |          |
  ┌+┬──|──────────┬─────────|─────────────|─────────────|───────|──────────|─────────────┐
  │%│┌─+───────┬─┐│┌──┬─────|─────────────|─────────────|───────|────────┬─|────────────┐│
  │ ││┌──┬─┬──┐│~│││[:│┌────|─────────────|─────────────|───────|─────┬─┐│┌+┬─┬────────┐││
  │ │││>:│@│i.││ │││  ││┌──┬|───────┬─────|─────────────|───────|────┐│~│││1│+│┌──┬─┬─┐│││
  │ ││└──┴─┴──┘│ │││  │││[:│+──┬─┬─┐│┌──┬─|─────────────|─┬─────|───┐││ │││ │ ││i.│@│*││││
  │ │└─────────┴─┘││  │││  ││~.│@│;│││[:│┌|───────────┬─+┐│┌─┬─┬+──┐│││ │││ │ │└──┴─┴─┘│││
  │ │             ││  │││  │└──┴─┴─┘││  ││+────────┬─┐│/.│││%│"│1 0││││ ││└─┴─┴────────┘││
  │ │             ││  │││  │        ││  │││┌─┬─┬──┐│<││  ││└─┴─┴───┘│││ ││              ││
  │ │             ││  │││  │        ││  ││││<│@│|.││ ││  ││         │││ ││              ││
  │ │             ││  │││  │        ││  │││└─┴─┴──┘│ ││  ││         │││ ││              ││
  │ │             ││  │││  │        ││  ││└────────┴─┘│  ││         │││ ││              ││
  │ │             ││  │││  │        ││  │└────────────┴──┘│         │││ ││              ││
  │ │             ││  │││  │        │└──┴─────────────────┴─────────┘││ ││              ││
  │ │             ││  ││└──┴────────┴────────────────────────────────┘│ ││              ││
  │ │             ││  │└──────────────────────────────────────────────┴─┘│              ││
  │ │             │└──┴──────────────────────────────────────────────────┴──────────────┘│
  └─┴─────────────┴──────────────────────────────────────────────────────────────────────┘

Çevrimiçi deneyin!


35:1+~.@;@([:<@|.`</.%~/~)@(1+i.@*)i.%
FrownyFrog

çok teşekkür ederim! Açıklamayı yeniden yapmayı gerektireceği için daha sonra tamamen güncelleyeceğim ...
Jonah

Ve 30:%i.~0~.@,@,[:]`|./.[:%/~1+i.@*
FrownyFrog

bu zekice, 0 ve ~ kullanın. boks ve artıştan kaçınmak için, onu seviyorum
Jonah

2

Python 3, 121 bayt

import math
def o(x,y):
 p=q=n=1
 while x*q!=p*y:a=p+q&1;p+=1+a*~-~-(p<2);q+=1-~-a*~-~-(q<2);n+=math.gcd(p,q)<2
 return n

2

Pas, 244 bayt

Üçgen sayı formüllerini kullanarak, yapbozun kısıtlamaları olmadan, bir "düz" zikzak "düz" ordinal bulmak için basit bir formül oluşturdum: https://www.mathsisfun.com/algebra/triangular-numbers.html . Bu, modülo 2 ile modifiye edildi, zig-zagların bulmacanın her bir çapraz sırasını yönlerine çevirdi. Bu işlev h ()

Sonra bu bulmacanın ana hilesi için: zig-zag izinde 3/3'e 1/1, 4/2'ye 2/1 gibi belirli tekrarlanan değerlerin 'sayılmaması'. 1-200 örnek koştum ve düz bir zig-zag üçgen sayacı ile bulmacanın istediği arasındaki farkın bir deseni olduğunu fark ettim. "Kayıp" sayıların paterni 5, 12, 13, 14, 23 vb. Olup OEIS'te bir isabetle sonuçlanmıştır. 3/3, 4/2 ve 1/1 gibi sayıları "tekilleştirmek" için Robert A Stump tarafından https://oeis.org/A076537 adresinde tarif edilenlerden biri için GCD> 1'in zikzaktaki tüm "önceki" ordinallerden x, y. Bu 'for' döngüleridir ve gcd olan g ().

Bazı yerleşik gcd ile daha kısa olurdu sanırım, ama ben çok kolay bir tane bulamadım (Rust ve Integer'de yeni bir tür im karıştı) ve bunun doğrudan tamsayı aritmetik kullandığını seviyorum, ve hiçbir yapı ya da kütüphane yoktur.

fn f(x:i64,y:i64)->i64 {
        fn h(x:i64,y:i64)->i64 {let s=x+y;(s*s-3*s+4)/2-1+(s+1)%2*x+s%2*y}
        fn g(x:i64,y:i64)->i64 {if x==0 {y} else {g(y%x,x)}}
        let mut a=h(x,y);
        for i in 1..x+y {for j in 1..y+x {if h(i,j)<h(x,y) && g(i,j)>1 {a-=1;}}}
        a
}

1

JavaScript (ES6), 86 bayt

Körili sözdiziminde girdi alır (p)(q).

p=>q=>(g=x=>x*y?x*q-y*p?g(x+d,g[x/=y]=g[x]||++n,y-=d):n:g(x+!~d,y+=!~(d=-d)))(d=n=y=1)

Çevrimiçi deneyin!


0

Javascript, 79 bayt

a=(p,q)=>p*q==1?1:1+((p+q)%2?q==1?a(p-1,q):a(p+1,q-1):p==1?a(p,q-1):a(p-1,q+1))

(Golf kodlamada yeniyim, bu yüzden bu muhtemelen kolayca iyileştirilebilir)

açıklama

let a = (p, q) => p * q == 1 // If they are both 1
    ? 1
    // Do a recursive call and increment the result by 1
    : 1 + (
        (p + q) % 2 // If on an even-numbered diagonal
        ? q == 1 // If at the beginning of the diagonal
            ? a(p - 1, q) // Go to previous diagonal
            : a(p + 1, q - 1) // Go one back
        : p == 1 // rougly the same
            ? a(p, q - 1)
            : a(p - 1, q + 1)
    )

4
(3,5)yol açmalıdır 19(değil 24) bu yana (1,1)==(2,2)==(3,3), (2,4)==(1,2), (4,2)==(2,1)ve (2,6)==(1,3). (yani (2,2)yol açmalıdır 1değil 5... vb)
Jonathan Allan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.