Her uzunlukta döngü içeren bir işlev bulun


11

Bir fonksiyon olduğu söylenir uzunluğunun döngüsü, n bir mevcutsa x kendi etki bu şekilde ön , n (x) = ve f m (x) ≠ x için 0 <m <n , üst simge n O anlamına gelir , n - katlama uygulaması f . 1 uzunluk döngüsünün sabit bir f (x) = x noktası olduğuna dikkat edin .

Göreviniz bir uygulamaktır bijective işlevi her olumlu uzunluğu tam olarak bir döngüsü vardır kendilerine tamsayılar gelen, n . İki yönlü bir işlev, bire bir yazışmadır, yani her tamsayı bir kez eşleştirilir. Uzunluğunun tam bir devir olması , n tam olarak var olduğu anlamına gelir n, farklı sayılar x olan f , n (x) = ve f m (x) ≠ x için 0 <m <n .

İşte böyle bir işlevin x = 0 etrafında nasıl görünebileceğine bir örnek :

x     ... -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7 ...
f(x)  ...  2  4  6 -3 -1  1 -4  0 -2  5  7 -7 -6  3 -5 ...

Bu alıntı 1 ila 5 arasındaki uzunluk döngülerini içerir :

n   cycle
1    0
2   -2  1
3   -4 -3 -1
4   -5  6  3  7
5   -7  2  5 -6  4
...

Yukarıda "işlev" i sadece matematiksel anlamda kullandığımı unutmayın. Giriş olarak tek (imzalı) bir tamsayı alır ve tek (imzalı) bir tamsayı döndürdüğü sürece, kendi dilinizde bir işlev veya tam bir program yazabilirsiniz. Her zaman olduğu gibi STDIN, komut satırı bağımsız değişkeni, işlev bağımsız değişkeni vb. Yoluyla giriş alabilir ve STDOUT, işlev dönüş değeri veya işlev (çıkış) bağımsız değişkeni vb. Aracılığıyla çıktı alabilirsiniz.

Tabii ki, birçok dil keyfi hassas tamsayıları (kolayca) desteklemez. Uygulamanız yalnızca en azından [-127, 127] aralığını kapsadığı ve dilin tamsayı türünün isteğe bağlı olarak değiştirilmesi durumunda rasgele tamsayılar için çalışacağı sürece, dilinizin yerel tamsayı türü aralığında çalışıyorsa iyi olur. hassas tamsayılar.

Standart kuralları geçerlidir.


2
Yakından alakalı. Farklılıklar küçük görünse de, eski yaklaşımların hiçbirinin önemli bir değişiklik yapmadan işe yaramadığını ima ediyorlar ve özellikle bu zorluğun kazanan yaklaşımının hiç uyarlanamayacağını düşünmüyorum.
Martin Ender

"her uzunlukta tam bir döngüye sahiptir", "her uzunluğunda birçok döngüye sahiptir": bu, diğerinden ayıran tek fark mıdır?
Abr001am

@ Agawa001 Bu bir fark, diğeri ise diğer zorluk pozitif tamsayılar üzerindeki fonksiyonlar hakkındadır, oysa bu zorluk tüm tamsayılarda bir fonksiyon ister.
Martin Ender

1
Döngü tanımınızın n'nin minimum olduğunu içermesi gerektiğini düşünüyorum. Aksi takdirde, 2 uzunluk döngüsü, 4 ve 6 uzunluk döngüsü vb. Sayılır.
xnor

@xnor Whoops, iyi bir nokta.
Martin Ender

Yanıtlar:


2

Pyth, 27 18 bayt

_h?gQ0^2Q*.5@,Q-xh

Açıklama (Pyth Qgiriş tamsayısına başlar):

_                       negative of (
                          (
  ?gQ0                      if Q >= 0:
      ^2Q                     2**Q
                            else:
         *.5                  half of
            @        Q          element Q (modulo list length) in
             ,                    the two element list [
              Q                     Q,
                 hQ                 ((Q plus 1)
                x  Q                 XOR Q)
               -    Q               minus Q
                                  ]
 h                        ) plus 1
                        )

Bunun döngüleri var

(−1)
(0, −2)
(1, −3, −4)
(2, −5, −7, −6)
(3, −9, −13, −11, −8)
(4, - 17, −25, −21, −15, −10)
(5, −33, −49, −41, −29, −19, −12)
(6, −65, −97, −81, −57, −37, −23, −14)
(7, −129, −193, −161, −113, −73, −45, −27, −16)
(8, −257, −385, −321, −225 , −145, −89, −53, −31, −18)
(9, −513, −769, −641, −449, −289, −177, −105, −61, −35, −20)

Uzunluğu döngüsü n verilir

( n - 2,
−2 ^ ( n - 2) ⋅1 - 1,
−2 ^ ( n - 3) ⋅3 - 1,
−2 ^ ( n - 4) ⋅5 - 1,
…,
−2 ^ 2 ⋅ (2 · n - 7) - 1,
−2 ^ 1⋅ (2 · n - 5) - 1,
−2 ^ 0⋅ (2 · n - 3) - 1).

Her bir k ≥ −1 tamsayısı , ( k + 2) döngüsünün ilk öğesi olarak görünür . Her bir k <−1 tamsayısı için, bazı i , j ≥ 0 için benzersiz olarak 1 - k = 2 ^ i ⋅ (2⋅ j + 1) ; daha sonra k (şekilde görüntülenir j + 2) (th elemanı i + j + 2) -cycle.


5

MATL , 47 bayt

E|G0<-QXJ:tQ*2/0hStJ<f0))Q2MQ)&:J6M-)2/ttk>Eq*k

Çevrimiçi deneyin!

Genel açıklama

Aşağıdaki işlev 2 @ Sp3000'in ilgili soruna verdiği cevapta kullanılanla aynıdır . @ Agawa001'e dikkat ettiğiniz için teşekkürler.

Fonksiyon üç bileşimi:

  1. Z'den (tamsayılara) N'ye ( doğallar ) bağlanma.
  2. Gelen eşleşme N için N arzu edilen karakteristiği (her uzunlukta bir döngü) ile yıkanmıştır.
  3. İşlev 1'in tersi.

İşlev 1 ve 3 kullanılır, çünkü N'de Z'ye göre istenen davranışı elde etmek daha kolaydır (sanırım) .

İşlev 2 aşağıdaki gibidir: üst satır alan, alt satır kod alan. Virgül netlik için kullanılır:

1,  2  3,  4  5  6,  7  8  9  10  ...
1,  3  2,  6  4  5, 10  7  8   9  ...

(Üst ilk blok 1daha düşük 1) uzunluğu 1. (ikinci bir döngüdür 2 3için 3 2) dairesel kaydırılmış üst kısmı, her blok vb uzunluğu 2, bir döngü, alt parça (işlevin görüntüsü) olduğu bir adım sağa.

İşlev 1 aşağıdaki gibidir:

 -5  -4  -3  -2  -1   0  +1  +2  +3  +4  ...
+10  +8  +6  +4  +2  +1  +3  +5  +7  +9  ...

İşlev 3, iki satır yer değiştirmiş olarak 1 ile aynıdır.

Örnekler

Görüntü 3DİR -5. İlk 3olarak 7fonksiyon 1 ile eşlenir ; daha sonra fonksiyon 2 7ile eşlenir 10; daha sonra 10fonksiyon 3 ile -5`e eşlenir.

Uzunluk-1 döngüsü 0. Uzunluk-2 döngüsü -1 1. Uzunluk-3 döngüsü -3 2 -2vb.

Kod açıklandı

Fonksiyon 1 ve 3 basittir.

İşlev 2, karşılık gelen giriş bloğunun alt uç noktasını bularak çalışır. Örneğin, eğer bu fonksiyona girdi ise 9bulur 7(yukarıdaki bloklara bakınız). Daha sonra 10, örnekteki üst uç noktayı seçer . Bloğun dairesel kayması, MATL'nin 1 tabanlı, modüler indeksleme sayesinde elde edilir.

         % FUNCTION 1
         % Implicit input
E|       % Multiply by two. Absolute value
G0<      % 1 if input is negative, 0 otherwise
-        % Subtract
Q        % Add 1
XJ       % Copy to clipboard J. Used as input to the next function

         % FUNCTION 2
:        % Range [1 2 ... J], where J denotes the input to this function
tQ*      % Duplicate, increment by 1, multiply
2/       % Divide by 2
0hS      % Prepend a 0. This is needed in case J is 0
tJ<f     % Duplicate. Find indices that are less than the input J
0)       % Pick the last index.
)        % Apply as index to obtain input value that ends previous block
Q        % Add 1: start of current block
2M       % Push the two arguments to second-to-last function call
Q)       % Add 1 and use as index: end of current block
&:       % Inclusive binary range: generate input block 
J        % Push J (input to function 2)
6M-      % Subtract start of block
)        % Apply as index (1-based, modular). This realizes the shifting

         % FUNCTION 3
2/       % Divide by 2
ttk>     % Duplicate. 1 if decimal part is not 0; 0 otherwise
Eq       % Multiply by 2, add 1
*        % Multiply
k        % Round down
         % Implicit display

Bu sp3000 s fonksiyon bir bükülme değil mi?
Abr001am

@ Agawa001 Oh, değil mi? Diğer zorluğu görmedim. Bir göz atacağım
Luis Mendo

Ah. Kesinlikle öyle. En azından bu, akıl yürütmemin orijinal olmasa bile doğru olduğunu açıklıyor :-)
Luis Mendo

yakın fikirleri yaymak için birden fazla zihnin ne kadar yakından çerçevelendiği şaşırtıcıdır.
Abr001am

4

Python 2, 55 bayt

g=lambda n,k=1:n/k and~g(~n+k*(n>0),k+1)+k*(n>0)or-~n%k

59 bayt:

g=lambda n,k=1:n<0and~g(~n,2)or n/k and k+g(n-k,k+2)or-~n%k

Döngüleri oluşturur

[0]
[-1, -2]
[1, 2, 3]
[-3, -4, -5, -6]
[4, 5, 6, 7, 8]
...

Dan Modifiye önceki meydan benim solüsyon elde değiştirilir, SP3000 inşası .

İşlev

g=lambda n,k=1:n/k and k+g(n-k,k+2)or-~n%k

negatif olmayan sayıların tek boyutlu döngülerini yapar

[0]
[1, 2, 3]
[4, 5, 6, 7, 8]
...

Doğru çevrim boyutunu bulmak için sonuç aralıkta oluncaya kadar kgirişi naşağı kaydırın . Bu aralığı işlemle tekrarlayın, ardından girişte yapılan tüm çıkarma işlemlerini geri alın. Bu, tarafından özyinelemeli olarak uygulanır .k=1,3,5,7,...[0,k)n->(n+1)%kk+g(n-k,k+2)

Şimdi, eşit döngüleri yapmak için negatiflere ihtiyacımız var. Not biz değiştirirseniz o gile başlamak k=2in g, hatta boyutlu döngüleri alırdım

[0, 1]
[2, 3, 4, 5]
[6, 7, 8, 9, 10, 11]
...

Bunlar, bit-tamamlayıcı yoluyla negatiflere etki eder ~. Yani, nnegatif ise, biz sadece değerlendirmek g(n)olarak ~g(~n,2).


Bunun işe yarayıp yaramadığını bilmiyorum, ama başka bir hesaplama yolu var kgibi görünüyor Math.floor(Math.sqrt(n))*2+1.
Neil

@Neil Sınırları ve döngü boyutlarını aritmetik olarak belirlemeye ve hatta tüm hesaplamayı bu şekilde yapmaya baktım, ancak bu ifadeler Python'da uzun ve özyinelemenin daha kısa olduğunu gördüm.
xnor

3

Python 3, 110 bayt

Hala oraya nasıl lambda getireceğimi anlamadım

n bir üçgen sayısı [1,3,6,10,15,21,28, vb.] ise f (n) listedeki sıra ile negatif bir çarpıdır. sayı negatifse, 1 + bir sonraki en küçük üçgen numarasını verin. başka, artış.

Örnek: 5 bir üçgen numarası değildir, bu nedenle 1 ekleyin.

Sonraki yineleme, 6'ya sahip. 6 bir üçgen numarası ve listede 3., yani -3 geliyor.

Program bu listeleri veriyor

uzunluk 1: [0]

uzunluk 2: [1, -1]

uzunluk 3: [2,3, -2]

uzunluk 4: [4,5,6, -3]

uzunluk 5: [7,8,9,10, -4]

x=int(input())
if x<0:print((x**2+x)/2+1)
else:
 a=((8*x+1)**.5-1)/2
 if a%1:print(x+1)
 else:print(-a)

Düzenleme: Fazla karakterleri kaldırmak için @TuukkaX'a tekrar teşekkürler.


1
Sen değişebilir 0.5için .5ve input('')için input().
Yytsi

2

Python 3, 146 bayt

0'dan büyük her sayı için çift döngüler (len 2,4,6,8 ...) ve 0'dan küçük tek döngüler (1,3,5,7) vardır. 0, 0 ile eşleşir.

(-3, -2, -1), (0), (1,2), (3,4,5,6)

ile eşleşir

(-2, -1, -3), (0), (2,1), (6,3,4,5)

f=lambda x:1+2*int(abs(x)**.5)if x<1 else 2*int(x**.5+.5)
x=int(input());n=f(x)
if x>0:b=n*(n-2)/4
else:b=-((n+1)/2)**2
print(b+1+(x-b-2)%n)

Düzenleme: @TuukkaX önceki çözümden 8 bayt çıkardı. Ve bir tane daha 3.


1
Ben ilk satırda if deyiminden önce bir boşluk kaldırabilirsiniz düşünüyorum . Ve midaha küçük bir şeyle değiştirilebilir b.
Yytsi

İşte aynı program aşağı golf:f=lambda x:1+2*int(abs(x)**0.5)if x<1 else 2*int(x**0.5+0.5) x=int(input()) n=f(x) if x>0:b=n*(n-2)/4 else:b=-((n+1)/2)**2 print(b+1+(x-b-2)%n)
Yytsi

1
Teşekkürler @TuukkaX. Ben 2 karakter değişkeni 'mi' unuttum.
Macenta

1
Ben de değişti input('')etmek input(). Alıntılar işe yaramaz çünkü sadece girişi almak istediğimizde konsola hiçbir şey yazdırmamız gerekmez.
Yytsi

1
Daha da kısa. Noktalardan önce sıfırlar kaldırıldı. f=lambda x:1+2*int(abs(x)**.5)if x<1 else 2*int(x**.5+.5) x=int(input());n=f(x) if x>0:b=n*(n-2)/4 else:b=-((n+1)/2)**2 print(b+1+(x-b-2)%n)
Yytsi

2

Matlab (423)

function u=f(n),if(~n)u=n;else,x=abs(n);y=factor(x);for o=1:nnz(y),e=prod(nchoosek(y,o)',1);a=log(x)./log(e);b=find(a-fix(a)<exp(-9),1);if ~isempty(b),k=e(b);l=fix(a(b));break;end;end,if(abs(n)==1)k=2;l=0;end,if(k==2)l=l+1;x=x*2;end,e=dec2base(l,k)-48;o=xor(e,circshift(e,[0 1]));g=~o(end);if(~o|nnz(o==1)~=numel(e)-g),u=n*k;else,if((-1)^g==sign(n)),u=sign(n)*k^(base2dec([e(2:end-1) 1]+48,k)-(k==2));else,u=n*k;end,end,end
  • Mümkün olduğu kadar kısaltmak için uğraşırken, rekabet etmeme nedeniyle son sıralama için iyi bir rekor kırıyor.

  • Benim matematiksel doğruluk ile ilgili bazı mantıksız hata kodumu sarkatist olarak büyük yapmak dışında bir yol bulamadık, diğer yandan tercih haritalama asal facors ve n-ary logaritma açısından oldu.

infaz

 f(2)

 1

 f(1)

 2

 f(-2)

 -4

 f(-4)

 -8

 f(-8)

 -1

 f(0)

 0



 ----------------------------

açıklama

  • Knonwing, ilk önce, herhangi bir sayı, bu üssün primer üslerinin bir ürünü olarak yazılabilir , N'nin mükemmel bir güç olduğu en küçük faktörün en büyük N=e1^x1*e2^x2...üssünden C(zorunlu olarak değil) çıkarılan döngülerin görüntülerini haritalamayı seçtim .

  • daha basit bir deyişle, let N=P^xP en küçük mükemmel kök olduğu, x: döngüsü için tam iki temel terimleri gösterir x=Ʃ(r*P^i)bir terim, Pdöngünün tabanı yanı ana numara N için mükemmel bir köküdür ve kdöngünün derecesi C=p^k, i1 ve k arasında değişir, katsayı r1 artar ve tüm katsayılar r = 1 olarak ayarlanana kadar aşağıdaki ön görüntü için P-1 ile sınırlanır, bu nedenle bu döngünün başlangıcına geçeriz.

  • Döngüler arasındaki çarpışmaları önlemek için, ürünlerden ziyade primerlerin üstelleştirilmesi seçimi doğrudur, çünkü iki baz döngüsünün bir örneği 3ve 2aralarındaki bir buluşma noktası olabilir 3*2, bu nedenle bir döngü, derecesi ile daha fazla tanımlandığından bu önlenir ve buluşma noktası için başka bir taban 6ve derece 1 döngüsü vardır .

  • Negatif sayılar bir istisna yerleştirir, gelince, negatif sayılar için tek dereceleri ve hatta geri kalanı için dereceleri ayırdım. Nasıl yani ?

    bir döngü içinde gömülü herhangi bir sayıda N P^k, olarak yazılır P^(a0*P^i0+a1*P^i1+...)miktarı (a0*P^i0+a1*P^i1+...)gibi, P-ary tabanında transalted edilir a0,a1,....(p = 2) dizisi, çiftli bir baz olması gerekir, bu noktayı açıklamak için,. Pozitif / negatif derece ve (+/- 1) istisna durumunu ayarlamadan önsöz olarak bilindiği gibi, bir dizi döngüsünün kenarlarında, kyalnızca dizi tüm bazlar için veya tüm bazlar için veya Ayazılırsa , bir N sayısıdır. rotasyona gerek yoktur, bu nedenle her ikisi için ilgili tek / çift dereceler için negatif / pozitif koşul atamak , formda yazılan tek bir sıra yapar , sırasıyla negatif / pozitif bir sayı döngüsünün başlangıç ​​kenarı için formda çift bir sıra yazılır .1111..{k+1}..10111..{k}..1k/k'101..{k}..100101..{k'}..10

    Misal:

    Bir numara alarak N=2^10, x=10=2^1+2^3sekans yazılı olduğu A=1010, sekansın bu tür pozitif sayı döngüsü, sonlu bir kenar symptomizes C=2^3sonraki resim bu kenarı başlama yani, A=011bir 8, ama bu sonucu standart hale ile, (+ / -) 1 istisna 2^10/2eşleştiren 8/2ve önceki görüntü döndürülebilir mustnt.

    Bir numara alarak N=-3^9, x=9=3^2sekans yazılı olduğu A=100, sekansın bu tür negatif bir sayı döngüsü, sonlu bir kenar symptomizes C=3^1sonraki resim bu kenarı başlama yani, A=01bir 3olumlu / Bu sonucu uyarlayarak, ama durum -3^9haritaları -3.

  • çift ​​için, sıradan bir döngüsel grup dizisinin başka bir biçimde yapıldığı kisvesi ile, (-/+)1döngü-baz sayıları içine girmesi öngörülüyordu , bu önceki öğelerin kaybolmasını önlüyor ve yapılan hareket sadece haşhaşla değişiyor yeni bir öğe.2{2,4}{8,16,32,64}..{1,2}{4,8,16,32}..


Sonuçlar:

döngüsel sayıların ilk makul aralıklarını doğrulamak için bu küçük kod sayfasını çalıştırma:

for (i=1:6) 
index=1;if(max(factor(i))>=5) index=0;end
for ind=0:index
j=f(((-1)^ind)*i); while(((-1)^ind)*i~=j)fprintf('%d ',j);j=f(j);end,fprintf('%d \n',(-1)^ind*i),pause,end,
end

Bu, bu sonuçlara yol açar

 2 1 
 -2 -4 -8 -1 
 1 2 
 -4 -8 -1 -2 
 9 27 3 
 -9 -27 -81 -243 -729 -2187 -6561 -19683 -3 
 8 16 32 64 128 256 512 4 
 -8 -1 -2 -4 
 25 125 625 3125 5 
 36 216 1296 7776 46656 6 
 -36 -216 -1296 -7776 -46656 -279936 -1679616 -10077696 -60466176 -362797056 -2.176782e+009 -1.306069e+010 ??? Error using ==> factor at 27

Sonuncusu segmentasyon hatasıdır ancak [-127,127] standart işaretli tam sayı aralığına uyar.


Bu tekniği bir süre önce eski bir C programımda hash işlevlerini tanımlamak için kullandım, düzgün çalışıyor!
Abr001am

0

JavaScript (ES6), 73 bayt

f=(n,i=0,j=0,k=0,l=1,m=i<0?-i:~i)=>n-i?f(n,m,k++?j:i,k%=l,l+!k):++k-l?m:j

Diziyi (0, -1, 1, -2, 2, -3, 3, ...) bulana kadar numaralandırarak çalışır n, döngüleri giderken sayar. igeçerli girişi içerir; jgeçerli döngünün başlangıcını, döngü kiçindeki dizini l, geçerli döngünün uzunluğunu mve dizideki bir sonraki girişi içerir. Biz bulduktan sonra nbiz o zaman almak jbir döngünün sonunda veya eğer mdeğilse.

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.