Palindrom mesafesi

Oct 02 2020

Belirli bir dizgenin aynı uzunluktaki en yakın palindromuna olan mesafeyi bulun.

Bu görev için, karakterlere, merkeze olan mesafeleriyle orantılı olarak, dizenin merkezinden daha uzaktaki karakterlere daha fazla ağırlık vermeye (bunu daha fazla torka katkıda bulunduğunu düşünün) karar verdim.

Bir dizge için palindrom mesafesini tanımlayalım \$s\$ dizginin merkezinden eşit aralıklarla yerleştirilmiş karşılık gelen çiftlerin mutlak farkının tüm çarpımlarının toplamı ve merkeze uzaklıkları olarak.

\$D_p=\displaystyle\sum_{i=1}^{d}\left(d-i+1\right)|s_i-s_{l-i+1}|\$

nerede \$l\$uzunluğu \$s\$ve \$d = \left\lfloor\frac{l}{2}\right\rfloor\$

Ortadaki karakter toplama herhangi bir katkı sağlamadığından, \$d\$tek uzunluklu dizeler için \$l\$eşittir \$d\$uzunluktaki dizeler için \$l-1\$.

Görev

Verilen dizge \$s\$uzunluğu> 1 bul \$D_p(s)\$

Giriş

Aşağıdakilerden biri:

  • dizi;
  • karakter listesi;
  • bir sayı listesi.

Çıktı

Bir tamsayı - giriş dizesinin palindrom mesafesi.

Test durumları

"aa" -> 0
"bab" -> 0
"abca" -> 1
"cbade" -> 6
"hello" -> 21
"code-golf" -> 45
"neveroddoreven" -> 0
"Neveroddoreven" -> 224

Kazanma kriterleri

Her dilde bayt cinsinden en kısa kod kazanır.

Kum havuzu

Yanıtlar

9 WheatWizard Oct 02 2020 at 18:50

Haskell , 50 bayt

u#(a:b)|c:d<-reverse b=u+(abs(c-a)+u)#d
u#_=u
(0#)

Çevrimiçi deneyin!

Anne bak! Çarpma yok! (veya bölme)

Açıklama

Bu cevap ne olduğunu açıklamak yerine yapar sadece kafa karıştırıcı olacağını düşündüğümüz, ben bu cevaba nasıl geldiğini ben kısaltılmış açıklama verecektir düşünüyorum.

Öncelikle Haskell özyinelemeli bir dildir, bu yüzden bunu özyinelemeli bir şekilde ifade etmek istiyoruz. Bir listemiz varsa, bunu yapmak oldukça kolaydır

[ a , d... , c ]

Sonra orta bitin "palindrom mesafesini" dalıp ekliyoruz abs(a-c)*(div(length d)2). Başka bir şeyse, cevap sıfırdır.

Şimdi Haskell'de son öğeyi elde etmek biraz zor, ancak ilkini elde etmek son derece basit. Dolayısıyla, son öğeyi elde etmenin bir yolu, listeyi tersine çevirip ilkini elde etmektir. Ortayı elde etmek için bunu orijinal sıraya geri döndürmeliyiz.

İlk buluşumuz, bir dizgiyi ters çevirdiğinizde "palindrom mesafesinin" değişmediğini fark etmektir. Bu nedenle, ters sıra üzerinde hesaplama yapmak her halükarda doğru sonucu vereceğinden, orta parçayı orijinal sırasına geri döndürmemiz gerekmez.

f(a:b)|c:d<-reverse b= ...

Yani tüm kodumuzda:

f(a:b)|c:d<-reverse b=f d+abs(a-c)*div(length d)2
f _=0

Tamam ama lengthve divbiraz masraflı. Geriye kalan adım sayısı gerçekten aradığımız şeydir, peki ya bunu bize yardım etmek için kullanırsak.

f(a:b)|c:d<-reverse b,(k,n)=(k+abs(a-c)*n,n+1)
f _=(0,1)
g=fst.f

Bu yardımcı olmadı, ama burada bir şeyin peşindeyiz. Çarpma sadece tekrarlanan toplamadır, bu yüzden gerçekten istediğimiz şey abs(a-c)kalan her yineleme için bir kez eklemektir . Öyleyse neden eklemek istediğimiz sayıları takip etmiyoruz ve onları aşağıya doğru eklemeye devam etmiyoruz.

u#(a:b)|c:d<-reverse b=sum u+(abs(c-a):u)#d
u#_=sum u
g=([]#)

İşte burada u, şimdiye kadarki tüm mutlak farklılıkların listesi olan bu ekstra argümanımız var. Ve her yinelemede bunların toplamını bir sonraki yinelemenin sonucuna ekliyoruz. Bu şekilde, her bir fark merkezden olan adım sayısı kadar, özünde merkezden uzaklığı ile çarpılarak eklenir.

Elbette sadece utoplamını istediğimizden , aslında değerleri ayırmamıza gerek yok, bazı baytlardan tasarruf etmek için sadece devam eden toplamı takip edebiliriz.

u#(a:b)|c:d<-reverse b=u+(abs(c-a)+u)#d
u#_=u
g=(0#)

Ve bu bize son kodu verir.

7 ovs Oct 02 2020 at 13:49

05AB1E , 8 bayt

Girişin tam sayılar listesi olarak alınabileceğini bana hatırlattığı için Kevin Cruijssen'e -1 bayt teşekkürler .

Âα2äθā*O

Çevrimiçi deneyin!

Yorum yaptı:

           # implicit input: a list of codepoints
          # push codepoints and codepoints reversed
 α         # take the (element-wise) absolute difference
  2ä       # split into 2 pieces
           # the last one will be shorter for odd lengths
    θ      # take the last piece
     ā     # length-range: [1, ..., length] (doesn't pop the TOS)
      *    # multiply element-wise
       O   # take the sum
5 DominicvanEssen Oct 02 2020 at 17:19

R , 50 47 bayt

Düzenleme: Giuseppe sayesinde %*%, elemanların çarpımını ayrı işlemler olarak toplamak yerine vektörlerin iç çarpımını hesaplamak için operatör kullanarak -3 bayt

abs((rev(x<-scan())-x)[(y=sum(x|1)/2):1])%*%1:y

Çevrimiçi deneyin!

Sayıların listesini kabul eder.

Golf oynamayan kod:

x=scan()                # x is vector of numbers
y=sum(x|1)/2)           # y is half the length of x
sum(                    # return the sum of...
 abs(                   # the absolute values of...
  (x-rev(x))            # the differences between each element of x
                        # and the same elements reversed...
   [y:1]                # at positions y..1
                        # (so only the first half, backwards)...
    *1:y))              # multiplied by 1..y
4 Noodle9 Oct 02 2020 at 18:57

C (gcc) , 74 \$\cdots\$ 52 51 bayt

Kaydedilen 6 7 sayesinde bayt AZTECCO !!!
Kaydedilen 9 bir boğmaca 15 sayesinde bayt Dominic van Essen !!!

f(s,l)int*s;{l=l>1?l/2*abs(*s++-s[l-=2])+f(s,l):0;}

Çevrimiçi deneyin!

Benim Limanı Python 3 cevap .

3 Arnauld Oct 02 2020 at 13:56

JavaScript (ES6),  61  57 bayt

ASCII kodlarının bir listesini bekliyor.

f=a=>1/a?0:(a.length>>1)*Math.abs(a.shift()-a.pop())+f(a)

Çevrimiçi deneyin!

Nasıl?

Bu, her yinelemede listeden ilk ve son girişi kaldıran, farklarının mutlak değerini hesaplayan ve ağırlığı uygulayan oldukça basit, özyinelemeli bir uygulamadır \$\lfloor L/2 \rfloor\$, nerede \$L\$ öğeler kaldırılmadan önceki listenin uzunluğudur.

Durdurma kriteri 1 / aşu durumlarda doğrudur:

  • a[]bu durumda boştur 1 / a == Infinity. Bu, giriş listesinin uzunluğu çift olduğunda olur.

  • Veya a[]listenin uzunluğu tuhafsa meydana gelen tek bir tamsayıdır. Özyinelemeyi başka bir hesaplama yapmadan güvenli bir şekilde durdurabiliriz çünkü tek bir karakter bir palindromdur ve bu noktada zaten nihai sonuca sahibiz.

3 ovs Oct 02 2020 at 18:10

Python 2 , 57 54 bayt

Tam sayılar listesi olarak girdi alan özyinelemeli bir işlev.

f=lambda l:l>[]and len(l)/2*abs(l[0]-l[-1])+f(l[1:-1])

Çevrimiçi deneyin!

Son kısım da abs(l[0]-l.pop())+f(l[1:])aynı uzunlukta olabilir.


Python 2 , 57 bayt

Özyinelemesiz biraz daha uzun bir yaklaşım.

lambda l:eval(len(l)/2*'+len(l)/2*abs(l.pop(0)-l.pop())')

Çevrimiçi deneyin!

3 Neil Oct 02 2020 at 18:35

Kömür , 22 bayt

IΣE∕θ²×⁻L∕θ²κ↔⁻℅ι℅§⮌θκ

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı sürümüne yöneliktir. Girdiyi dizge olarak alır (bir dizeyi yarıya indirmek, diziyi yarıya indirmekten daha iyidir). Açıklama:

    θ                   Input string
   ∕ ²                  First half
  E                     Map over characters
            κ           Current index
       ⁻                Subtracted from
        L∕θ²            Length of half of string
      ×                 Multiplied by
             ↔⁻         Absolute difference of
               ℅ ℅      Ordinals of
                ι       Current character and
                  §     Character at
                     κ  Current index in
                   ⮌    Reversed
                    θ   Input string
 Σ                      Take the sum
I                       Cast to string
                        Implicitly print

Alternatif yaklaşım, ayrıca 22 bayt:

IΣE⮌∕⮌θ²×⊕κ↔⁻℅ι℅§⮌∕θ²κ

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı sürümüne yöneliktir. Açıklama:

      θ                 Input string
     ⮌                  Reversed
    ∕  ²                "First" half
   ⮌                    Reversed i.e. last "half"
  E                     Map over characters
          κ             Current index
         ⊕              Incremented
        ×               Multiplied by
           ↔⁻           Absolute difference of
             ℅ ℅        Ordinals of
              ι         Current character and
                §       Character at
                     κ  Current index in
                 ⮌      Reversed
                  ∕θ²   First half of input string
 Σ                      Take the sum
I                       Cast to string
                        Implicitly print
3 GunterLiszewski Oct 08 2020 at 06:34

TECO , 53 Bayt

  1. Q-register A, başlatma koduna sahiptir.
*:ga

$$ j0uaz-1ub0uu0uw$$*
  1. Q-register M hepsini bir araya getiriyor. Sonuç, Q-register W'de kalır.
:gm$$ z/2<0ua0a-(qba)%a"L-qaua'qa%u%w$c-2%b>$$*
  1. “Neveroddoreven” ın \ $ D_p \ $ hesaplamasına bir örnek : tüm tamponu öldürün, kelimenizi ekleyin, A, B, U ve W kayıtlarını ilklendirin ve tamponun başlangıcına atlayın; sonra z / 2 kez yineleyin, W yazmacında biriktirin; son olarak W kaydının sayısal içeriğini göster.
hkiNeveroddoreven$mamm$$ *qw=$$
224
*
  1. Tam program ve uzunluğu.
*ht$$ j0uaz-1ub0uu0uwz/2<0ua0a-(qba)%a"L-qaua'qa%u%w$c-2%b>*z=$$
53
  1. Test durumları.
"aa" -> 0
"bab" -> 0
"abca" -> 1
"cbade" -> 6
"hello" -> 21
"code-golf" -> 45
"neveroddoreven" -> 0
"Neveroddoreven" -> 224

Bu, her bir test kelimesini boşaltılmış düzenleme arabelleğine ekleyen , ardından Q-yazmaçları A ve M makrolarını çağıran ve son olarak sayısal Q-yazmacı W'de toplanan \ $ D_p \ $ gösteren bir TECO oturumunu gösterir.

*hkiaa$mammqw=$$ 0 *hkibab$mammqw=$$ 0 *hkiabca$mammqw=$$ 1 *hkicbade$mammqw=$$ 6 *hkihello$mammqw=$$ 21 *hkicode-golf$mammqw=$$ 45 *hkineveroddoreven$mammqw=$$ 0 *hkiNeveroddoreven$mammqw=$$
224
2 Razetime Oct 02 2020 at 22:54

APL (Dyalog Unicode) , 21 bayt

{+/|⍵×⍳≢⍵}(⌈2÷⍨⍴)↓⊢-⌽

Çevrimiçi deneyin!

2 AZTECCO Oct 02 2020 at 19:19

C (gcc) , 55 52 bayt

f(a,z)char*a;{z=z/2?z/2*abs(*a++-a[z-=2])+f(a,z):0;}

Çevrimiçi deneyin!

  • @ Noodle9'dan çalmaktan ve yeniden düzenlemelerden biraz kurtardı
f (a, z) char * a; {z = - bir C-string işaretçisini ve uzunluğunu takip eden fonksiyon
                    ve eax yazmacı üzerinden geri dönüyor.

z / 2? - merkezde değilse:
f (a + 1, z-2)> işaretçi hareket ettirilmiş ve uzunluk azaltılmış olarak özyinelemeli olarak çağırın 
+ abs (* aa [z-1]) * (z / 2)  
              - çiftlerin değerini ekleyin
: 0;}> yoksa r'yi 0'a başlat
2 JonathanAllan Oct 03 2020 at 02:37

Jöle , 7 bayt

ạṚŒHṪḋJ

Bir tamsayı veren tam sayıların bir listesini kabul eden monadik bir Bağlantı.

Çevrimiçi deneyin!

Nasıl?

ạṚŒHṪḋJ - Link: list of integers, A   e.g. (Abracadabra) [65,98,114,97,99,97,100,97,98,114,97]
 Ṛ      - reverse (A)                                    [97,114,98,97,100,97,99,97,114,98,65]
ạ       - absolute difference (vectorises)               [32,16,16,0,1,0,1,0,16,16,32]
  ŒH    - split in two (1st part longest, if any)        [[32,16,16,0,1,0],[1,0,16,16,32]]
    Ṫ   - tail                                           [1,0,16,16,32]
      J - range of length (of A)                         [1,2,3,4,5,6,7,8,9,10,11]
     ḋ  - dot-product                                    273 (= 1×1+0×2+16×3+16×4+32×5+0×6+...0×11)
2 JoKing Oct 03 2020 at 20:46

Kabuk , 14 12 11 bayt

-2 Wheat Wizard sayesinde kod noktalarının bir listesi olarak girdi alabileceğinizi işaret ediyor

ve -1 sayesinde HP.Wiz, ≠'nin yalnızca eşitsizlik değil, mutlak fark olduğunu gösterir

ΣFoz*ŀ½Sz≠↔

Çevrimiçi deneyin!

Açıklama

       Sz≠      Zip absolute difference the list from
          ↔    The reverse of the list
      ½         Split the list into two halves (with the longer being the first)
 F              Reduce by
  o  ŀ          Converting the first half to range(1, length)
   z*           And zip multiplying with the second half
Σ               Finally sum the absolute values
1 att Oct 02 2020 at 15:01

Wolfram Dili (Mathematica) , 53 bayt

f@_:0=0
f[a_,b___,c_]:=Abs[a-c]⌈Length@a?b/2⌉+f@b

Çevrimiçi deneyin!

Tam sayıların bir listesini alır.

Length@a?büzerinden bir bayt kaydeder Tr[1^{a,b}]/ Length[a.b]sayesinde PatternTestbireyin yüksek öncelik.

1 Noodle9 Oct 02 2020 at 18:22

Python 3 , 59 bayt

f=lambda l:len(l)>1and len(l)//2*abs(l.pop(0)-l.pop())+f(l)

Çevrimiçi deneyin!

1 Jonah Oct 03 2020 at 23:19

J , 24 bayt

+/@(#\.@]*|@-)&(,~inv)|.

Çevrimiçi deneyin!

Girdiyi tamsayılar listesi olarak alır.

J'de kısaca ifade etmesi beklenmedik bir şekilde zor olan ilginç sorunlardan bir diğeri birkaç yaklaşım denedim ve bu benim en iyi girişimim.

Nasıl

  • (...)|.Tüm ifade bir kancadır, yani orijinal girdi ve tersine çevrilen girdi |., sırasıyla sol ve sağ bağımsız değişkenler olarak parantez içindeki ifadeye aktarılacaktır.
  • (...)&(,~inv)Oluşturma bağlacı &bu durumda her iki bağımsız değişkeni de belirtilen fiille dönüştürür ,~inv.
    • ,~invBir listeyi kendi kendine ekleyerek ikiye katlayan fiilin tersidir ,~. Bu işlemin tersi, listenin ilk yarısını almaktır ve bu, tek sayılar için "aşağı yuvarlama" olur, ki biz de burada istediğimiz şey budur.
  • #\.@]*|@-#\.@]Element-wise ile çarpın|@-
    • |@-iki liste argümanını eleman bazında çıkarın ve mutlak değeri alın |. Bunlar "mesafeler" dir.
    • #\.@]örneğin 4 3 2 1listelerin uzunluğu 4 ise üretir . Bunu #\., doğru argümanın son ek uzunluklarını alarak yapar ]. Sol argümanı burada da kullanabilirdik.
  • +/@ Sonucu toplayın

Karşılaştırma için, J'ye dönüştürülen APL çözümü 25 bayttır:

>.@-:@#(1#.]*&|#\)@}.]-|.

Çevrimiçi deneyin!