Bölünebilirlik-7 kuralını uygulamak


25

Ondalık bir sayının 7 ile bölünebilir olup olmadığını kontrol etmek için:

Son basamağı silin. 2 ile çarpın ve kalandan çıkarın. Sonuç 7 ile bölünebilirse, orijinal sayı 7 ile bölünebilir.

(ayrıca örneğin burada tanımlanmıştır )

Bu kural manuel bölünebilirlik kontrolü için iyidir. Örneğin:

2016 7 ile bölünebilir mi?

6*2201'den çıkarma ; biz 189 olsun. Bu 7 ile bölünebilir mi? Kontrol etmek için kuralı tekrar uygulayalım.

9*218 den çıkartın ; 0 alırız. Bu nedenle, 2016 7 ile bölünebilir.

Bu zorlukla mücadelede, bölünebilirlik durumu açık olana , yani sayı 70'den büyük olmayana kadar bu kuralı uygulamalısınız (ancak, ayrıntılar için aşağıya bakınız). Bir işlev veya tam bir program yapın.

Giriş : pozitif bir tamsayı; Kodunuz 32767'ye kadar olan girişleri desteklemelidir (isteğe bağlı hassas tam sayıların desteklenmesi bir bonus; aşağıya bakınız).

Çıktı : 7'ye bölünebilirlik kuralını sıfır veya daha çok kez uygulamanın bir sonucu olan, 70'den büyük olmayan bir tamsayı (muhtemelen negatif).

Test durumları:

Input                   Output      Alternative output

1                       1
10                      10          1
100                     10          1
13                      13          -5
42                      42          0
2016                    0
9                       9
99                      -9
9999                    -3
12345                   3
32767                   28          -14

---------- Values below are only relevant for the bonus

700168844221            70          7
36893488147419103232    32          -1
231584178474632390847141970017375815706539969331281128078915168015826259279872    8

İki olası çıkış belirtildiğinde, sonuçlardan biri doğrudur: ikincisi kuralın bir kez daha uygulanmasına karşılık gelir. Kuralı tek haneli bir sayıya uygulamak yasaktır: rakamı silerseniz hiçbir şey (0 değil) kalır.


Bonus : Eğer algoritmanız varsa

nerede nondalık basamak sayısıdır:

Kodunuzun bayt sayısından% 50 çıkarın.

Gerçek bonus :

Ek olarak, eğer algoritmanız girdiyi normal yönde okursa, en önemli basamaktan başlayarak, bir kez daha% 50'yi çıkarın - puanınız bayt sayınızın% 25'idir (bu mümkün gibi görünüyor, ama kesinlikle emin değilim).


1
@DenkerAffe Girişi olduğu gibi döndürmek kabul edilebilir. Bunu yansıtmak için girdi = 10 test durumunu güncelledim; En başından beri fikir buydu.
anatolyg

4
Bu kuralı üzerinde kullanmak istemem 1000000000000000000001.
Neil,

1
Ancak, dilinizde long longyerleşik bir eşdeğer tür veya dil varsa ?
SuperJedi224

1
Söylediğim şey, bazı uygulamalarda, bu son test durumu için yeterince büyük olan 128-bit bir tamsayıydı.
SuperJedi224,

7
-1. Tüm diller keyfi kesinliği desteklemez.
Mart Ho,

Yanıtlar:


23

Golf Betiği, 27 22 bayt

{.9>{.10/\10%2*-f}*}:f

Bu şekilde kullanabilirsiniz:

1000f

açıklama

{.9>{.10/\10%2*-f}*}:f
{                  }:f    # Define block 'f' (similar to a function)
 .                        # Duplicate the first value of the stack
  9>{            }*       # If the value on top of the stack is greater than 9 then the block is executed
     .10/\10%2*-          # Same as nb/10 - (nb%10 * 2) with some stack manipulations '.' to duplicate the top of the stack and '\' to swap the the first and second element of the stack
                f         # Execute block 'f'

Dennis sayesinde 5 bayt kurtarıldı!


1
Programming Puzzles ve Code Golf'a hoş geldiniz. Bu iyi bir cevap, ancak yukarıdaki sorulardaki gibi bir kod dökümü ve açıklama ekleyerek daha da geliştirebilirsiniz. Bu yorumu yanıtlamak için, bir yorumun (veya herhangi bir yerinde) başının içine @wizzwizz4( @sonra kullanıcı adım) yazın .
wizzwizz4

1
@ wizzwizz4 Daha iyi? 'Kod analizi' ile ne demek istediğinizi anladığımdan emin değilim (anadili üzgünüm değil)
Dica

8
İnanıyorum ki "kod çözümlemesi" ile eklediğin bir açıklama. Bu gerçekten çok güzel bir ilk cevap. Siteye Hoşgeldiniz!
Alex A.

1
Parçayı, tarafından itilen değere bağlı {...}{}ifolarak {...}*, yalnızca bir kez sıfır kod kodunu uygulayacak şekilde yeniden yazabilirsiniz >. Ayrıca, biz bir daha yineleme (böylece yerine gerçekleştirmek için izin konum 70ile 9bir bayt kaydeder) ve senin ile blok pop gerek olduğunu düşünmüyorum ;.
Dennis,

3
@Dica, bu sadece 624 görüntülemeyle bir soru üzerine 12+ oy almak ve iki moderatörden övgü almak için yeterince iyi bir ilk cevap. Bunu devam ettirirseniz, yakında Dennis'i ele geçireceksiniz!
wizzwizz4

13

Haskell, 35 bayt

until(<71)(\n->div n 10-2*mod n 10)

Kullanım örneği: until(<71)(\n->div n 10-2*mod n 10) 36893488147419103232-> 32.

Açıklamak için çok fazla bir şey yok, bu algoritmanın doğrudan bir uygulamasıdır.


9

Jöle, 11 bayt

d⁵Uḅ-2µ>9$¿

Çevrimiçi deneyin!

Nasıl çalışır

d⁵Uḅ-2µ>9$¿  Main link. Input: n

d⁵           Divmod; return [n : 10, n % 10].
  U          Upend; yield [n % 10, n : 10].
   ḅ-2       Convert from base -2 to integer, i.e., yield -2 × (n % 10) + (n : 10).

      µ      Push the previous chain as a link and begin a new, monadic chain.
          ¿  Apply the previous chain while...
       >9$     its return value is greater than 9.

Ve her zamanki gibi Jelly kazanır. Dennis, Jelly’de bir jöle tercümanı uygulamak ne kadar sürer?
Bálint

6

Python 2,38 bayt

f=lambda x:f(x/10-x%10*2)if x>70else x

Burada dene !

Basit özyinelemeli yaklaşım. Aksi durumda <70, bölünebilirlik kuralını uygular ve kendisini sonuçla çağırırsa x değerini yazdırır.


Eğer sonra boşluk gerekmez)
Maltysen

@Maltysen Doğru. Kopyala yapıştırılan yanlış, ipucu için teşekkürler!
Denker

2
İf çok ayrıntılı. f=lambda x:x*(x<70)or f(x/10-x%10*2)
saat

1
@Seeq Güzel hile, teşekkürler! Bu teoride çalışmalı, ancak versiyonum çalışmadığı sürece 2016 yılında girdi olarak maksimum özyineleme derinliğine ulaşıyor. Neden bir fikrin var mı?
Denker

Ah, doğru, bunu düşünmedim. Bu numara x*(x<70) != 0, son koşul olarak kabul edilir. Eğer x 0'a ulaşırsa - 2016'da olduğu gibi - son durum asla olmaz.
saat

6

Pyth, 13 bayt

.W>H9-/ZTyeZQ

Çevrimiçi deneyin: Gösteri veya Test Paketi

Bu, tüm alternatif cevapları yazdıracaktır.

Açıklama:

.W>H9-/ZTyeZQ   
            Q   read a number from input
.W              while
  >H9              the number is greater than 9
                do the following with the number:
      /ZT          divide it by 10
     -             and subtract
         yeZ       2*(number%10)

5

Julia, 27 26 bayt

f(x)=x>9?f(x÷10-x%10*2):x

Bu bir tamsayı kabul eden ve a döndüren özyinelemeli bir işlevdir BigInt. Girdi, son örnekte olduğu gibi çok sayıdaysa, Julia bunu a olarak ayrıştırır BigInt, bu nedenle el ile dönüştürmeye gerek yoktur.

Yaklaşım, algoritmanın basit bir uygulamasıdır. Alternatif çıkışlar üretecektir. Modülü 10'a böldürmek son rakamı, tam sayı bölümünden kalan bölümü ise 10 rakamı dışında her şeyi verir.

Dennis sayesinde bir bayt kaydedildi!


Böylece yerine bir tane daha yinelemeyi gerçekleştirmek için izin konum 70ile 9bir byte kaydeder.
Dennis,

@Dennis İyi arama, teşekkürler!
Alex A.

4

Pyth, 17 bayt

L?<b70by-/bT*%bT2

Burada dene!

Python cevabımda olduğu gibi özyinelemeli yaklaşım . Bir lambda tanımlar yböyle denir: y12345.
Online tercümandaki bayt sayacı 19 bayt gösterir çünkü lambda çağrısını ona ekledim, böylece sadece run butonuna basarak deneyebilirsiniz.

açıklama

L?<b70by-/bT*%bT2

L                  # Defines the lambda y with the parameter b
 ?<b70             # if b < 70:
      b            # return b, else:
       -/bT*%bT2   # calculate b/10 - b%10*2 and return it

Açıklamasında bir yazım hatası var, 17 70 olmalı: P
FryAmTheEggman

4

CJam - 19 bayt

Do-while sürümü:

r~A*{`)]:~~Y*-_9>}g

Çevrimiçi deneyin ya da sürüm 1 iken:

r~{_9>}{`)]:~~Y*-}w

Çevrimiçi olarak deneyin veya sürüm 2 iken:

r~{_9>}{_A/\A%Y*-}w

Çevrimiçi deneyin .

r~                     | Read and convert input
  A*                   | Multiply by 10 to get around "if" rule
     `                 | Stringify
      )                | Split last character off
       ]               | Convert stack to array
        :~             | Foreach in array convert to value
          ~            | Dump array
           Y*          | Multiply by 2
             -         | Subtract
              _        | Duplicate
               9>      | Greater than 9?
    {            }g    | do-while

3

Oracle SQL 11.2, 116 bayt

WITH v(i)AS(SELECT:1 FROM DUAL UNION ALL SELECT TRUNC(i/10)-(i-TRUNC(i,-1))*2 FROM v WHERE i>70)SELECT MIN(i)FROM v;

Un-golfed

WITH v(i) AS
(
  SELECT :1 FROM DUAL
  UNION ALL
  SELECT TRUNC(i/10)-(i-TRUNC(i,-1))*2 FROM v WHERE i>70
)
SELECT MIN(i) FROM v;

3

Haskell, 157 192 184 167 159 147 138 + 5 bayt -% 50 = 71,5 bayt

O (1) boşluk, O (n) süre, tek geçiş!

h d=d%mod d 10
d%r=(quot(r-d)10,r)
p![d]=d-p*10
p![d,e]=d#(e-p)
p!(d:e:f)|(b,a)<-quotRem(2*d)10,(q,r)<-h$e-a-p=(b+q)!(r:f)
m#0=m
m#n=n-2*m
(0!)

0![6,1,0,2]Kuralı 2016'ya uygulamak için kullanın , yani ilk önce en az önemli rakam olan akış biçiminde bir sayı iletin. Bu şekilde, O (1) uzay karmaşıklığı ile kuralı uygulayarak rakamın rakamını basamak basar.

Ungolfed kodu burada:

import Data.Char

{- sub a b = sub2 0 a b
  where
    sub2 borrow (a:as) (b:bs) = res : sub2 borrow2 as bs
      where
        (borrow2, res) = subDig borrow a b
    sub2 borrow (a:as) [] = sub2 borrow (a:as) (0:[])
    sub2 _ [] _ = [] -}

--subDig :: Int -> Int -> Int -> (Int, Int)
subDig borrow a b = subDig2 (a - b - borrow)
  where
    subDig2 d = subDig3 d (d `mod` 10)
    subDig3 d r = ((r-d) `quot` 10, r)

seven ds = seven2 0 ds
seven2 borrow (d:e:f:gs) = seven2 (b + borrow2) (res:f:gs)
  where
    (a, b) = double d
    (borrow2, res) = subDig borrow e a
seven2 borrow (d:e:[]) = finalApp d (e-borrow)
seven2 borrow (d:[]) = d - borrow*10

double d = ((2*d) `mod` 10, (2*d) `quot` 10)

finalApp m 0 = m
finalApp m n = n - 2*m

num2stream :: Int -> [Int]
num2stream = reverse . map digitToInt . show
sev = seven . num2stream

Bunun nasıl yürüdüğünün özü, bir rakam basamağı çıkarma algoritmasını uygulamasıdır , ancak çıkarılacak her sayının en fazla 2 basamak olması ve bu sayede 1 - 1 arasında isteğe bağlı bir rakam çıkartabilmemiz avantajından yararlanır. veya - ana rakamdan 2 basamaklı sayılar (en az önemli basamakları yemek gibi).

Çıkarma algoritması O (1) 'dir ve yalnızca mevcut' ödünç 'değerini saklar. Bunu fazladan rakam (0 veya 1) eklemek için değiştirdim ve bu ödünç değerinin sınırlandığını not ettik ([-2,2] aralığında, bu yüzden bunu depolamak için sadece 3 bite ihtiyacımız var).

Belleğe kaydedilen diğer değerler, eklenecek geçerli 2 basamaklı sayıyı temsil eden, akışta bir ileriye bakacak ve çıkarma algoritmasının bir basamağını uygulayan geçici değişkenlerdir (yani iki basamak alır ve bir ödünç değeri alır ve geri döner). bir basamak ve yeni bir borçlanma değeri).

Sonunda akıştaki son iki basamağı bir kerede bir basamak listesi yerine tek basamaklı bir rakam döndürmek üzere bir kerede işler.

Not: Eski sevmodel versiyonundaki fonksiyon, üzerinde çalışacak Integerve ters akış formuna dönüştürülecektir.


Bonusu normal rakamlar için vermeyi planladım. Ama ben asla söylemedim, bu yüzden daha az eğlenceli olsa bile, tersine verilen sipariş için bonusu almak adil olur. Her neyse, tersine sipariş bile düşündüğümden daha zor, bu yüzden yeterince eğlenceli!
anatolyg

@anatolyg: Teşekkürler! Tek bir pasoyu (1) normal düzenin uygulamasıyla yapıp yapamayacağımdan emin değilim ... kural en az önemli rakamlara dayanır, bu nedenle teoride kuralın doğrudan uygulanması ters düzen dışında imkansızdır. Aklıma gelen tek şey matematiksel olarak eşdeğer bir form bulmaktır - örneğin Mod[18 - Quotient[n, 10] - 2*n, 21] - 18 + Quotient[n, 10]10 ile 99 arasında n için ampirik olarak çalışır, ancak n'in sahip olduğu rakamların sayısı daha da artar ...
azot

Hmm düşündüm ve öndeki 2 haneyi koruyarak ve sonraki her basamağı uygulayarak bir yol olabileceğini düşündüm, fakat 'filtrelemeyi' hesaba katıncaya kadar (-2) ^ n ile çarptım. bellekte tüm rakamları tutmak ve o (1) ödün vermeden bu işi yapmak için bir yol yoktur olsa anlarım 'lık hatta o (n)' lık ... Ben normal bir düzen :( kesinlikle imkansız olduğunu düşünüyorum
azot

1
Korkarım 0arama yaparken ilklerin baytını saymanız gerekiyor.! , örneğin bir bölüm (0!)(+ yeni bir satır), yani +5 bayt. Diğer tarafta deseni maçları ilk kısaltabilir !için p![d]=ve p![d,e]=. Ayrıca let: yerine desen koruyucu kullanın p!(d:e:f)|(b,a)<-quotRem(2*d)10,(q,r)<-h$e-a-p=(b+q)!(r:f).
nimi

1
@nitrous: Oh (0!), kendi hattında bahsettim . (0!)Cevap olarak verdiğiniz işlev. Bu 0gereklidir, ancak girişle ilgisi yoktur, bu yüzden arayan kişiye dış kaynak kullanamazsınız. Tabii ki de kullanabilirsiniz f x=0!x, ama bu daha uzun.
nimi

3

GNU dc, 20 15 bayt

[10~2*-d70<F]sF

Bu benim ilk (hiç) dc fonksiyonumu tanımlar F. Yığının üstüne girdi alır ve çıktısını yığının üstüne bırakır. Örnek kullanım:

36893488147419103232
lFxp
32

2

Mathematica, 47 44 bayt

If[#>70,#0[{1,-2}.{⌊#/10⌋,#~Mod~10}],#]&

Basit özyinelemeli yaklaşım. Muhtemelen daha da golf oynayabilirdi.


#0[{1,-2}.QuotientRemainder[#,10]]bir bayt kaydeder.
njpipeorgan,

2

R, 43 bayt

x=scan();while(x>70)x=floor(x/10)-x%%10*2;x

Açıklama:

x=scan()                                      # Takes input as a double
        ;                                     # Next line
         while(x>70)                          # While-loop that runs as long x > 70
                      floor(x/10)             # Divide x by 10 and round that down
                                 -x%%10*2     # Substract twice the last integer
                    x=                        # Update x
                                         ;    # Next line once x <= 70
                                          x   # Print x

Örnek çalışır:

> x=scan();while(x>70)x=floor(x/10)-x%%10*2;x
1: 9999
2: 
Read 1 item
[1] -3

> x=scan();while(x>70)x=floor(x/10)-x%%10*2;x
1: 32767
2: 
Read 1 item
[1] 28

1

JavaScript ES6, 38 bayt

a=i=>i>70?a(Math.floor(i/10)-i%10*2):i

36893488147419103232Ve kullanarak başarısız~~(1/10) da başarısız olur700168844221

Ölçek:

a=i=>i>70?a(Math.floor(i/10)-i%10*2):i
O.textContent = O.textContent.replace(/(-?\d+) +(-?\d+)/g, (_,i,o) =>
  _+": "+(a(+i)==o?"OK":"Fail")
);
<pre id=O>1                       1
10                      10
100                     10
13                      13
42                      42
2016                    0
9                       9
99                      -9
9999                    -3
12345                   3
700168844221            70
36893488147419103232    32</pre>


İki Failsaniye ... 70 ve 32
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Evet, hala merak ediyorum neden ...
andlrc

Çünkü en azından JavaScript'in numara tipi son durumu ele almıyor.
Conor O'Brien,

1
f=n=>n>70?f((n-n%10*21)/10):ndaha kısa bir versiyondur ancak yine de sadece çalışır 2**56.
Neil

@ Ne keyfi hassasiyet için cevabımı görüyorsun ve büyük takdir, golf oynamak için çekinmeyin.
Patrick Roberts

1

Mathematica, 33 bayt

#//.a_/;a>70:>⌊a/10⌋-2a~Mod~10&

Test durumu

%[9999]
(* -3 *)

1

Perl 5, 47 46 bayt

bigintSon test davası için kullanmak zorunda kaldım . (20 olmadan döner)

use bigint;$_=<>;while($_>9){$_-=2*chop;}print

Bonus için bir aday olduğundan emin değilim, bu yüzden hesaba katmadım. (Sanırım öyle ama kavramlara pek alışkın değilim)

Burada dene!


1

ES6, 108 bayt

f=(s,n=0)=>s>1e9?f(s.slice(0,-1),((1+s.slice(-1)-n%10)%10*21+n-s.slice(-1))/10):s>9?f(((s-=n)-s%10*21)/10):s

2² ve 1000000000000000000001 için çalışır, ancak daha fazla golf kullanabilir.


@PatrickRoberts Hata, gönderim için yeniden biçimlendirme yapılırken gözetim.
Neil

1

JavaScript ES6, 140 142 bayt

f=s=>s>9?eval("t=s.replace(/.$/,'-$&*2');for(i=-1;0>(n=eval(u=t[c='slice'](i-4)))&&u!=t;i--);n<0?n:f(t[c](0,i-4)+('0'.repeat(-i)+n)[c](i))"):s

Bu gerçek rasgele kesinlikli matematiktir, hatta en büyük test senaryosunda bile çalışır.

Bu fonksiyon diziden son basamağı yinelemeli olarak kaldırır, daha sonra farkın pozitif olana kadar eksiğe uygulanacak basamak miktarını yinelemeli olarak artırarak kalan basamağı kalan sayısal dizgeden 2 x çıkarır. Sonra, uygun şekilde yastıklı 0s bulunan dizgenin sonuna olan farkı ekler ve sayısal değeri eşit veya daha küçük olana kadar özyinelemeli olarak çağırır 9.

  • @Neil sayesinde golf oynadı 7 bayt (evet, 2 bayt kazandığımı biliyorum ama işlevin donmasına ya da bazı durumlarda yanlış çıktı döndürmesine neden olan birkaç hata giderdim).

f=s=>s>9?eval("t=s.replace(/.$/,'-$&*2');for(i=-1;0>(n=eval(u=t[c='slice'](i-4)))&&u!=t;i--);n<0?n:f(t[c](0,i-4)+('0'.repeat(-i)+n)[c](i))"):s;[['1',1],['10',1],['100',1],['13',-5],['42',0],['2016',0],['9',9],['99',-9],['9999',-3],['12345',3],['700168844221',7],['36893488147419103232',-1],['231584178474632390847141970017375815706539969331281128078915168015826259279872',8]].map(a=>document.write(`<pre>${f(a[0])==a[1]?'PASS':'FAIL'} ${a[0]}=>${a[1]}</pre>`))


Güzel, ama işe yaramayabilir 1000000000000000000001.
Neil

1
Dene s.replace(/.$/,'-$&*2'). Üzgünüm ama gerisi için bariz bir fikrim yok.
Neil

1

C #, 111 104 bayt

int d(int n){var s=""+n;return n<71?n:d(int.Parse(s.Remove(s.Length-1))-int.Parse(""+s[s.Length-1])*2);}

1

Brain-Flak , 368 360 bayt

Çevrimiçi Deneyin!

([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>){{}(({}))(<((()()()()()){}<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>([([([(({}<{}><>)<([{}]{})(<((()()()()()){}(<>))>)<>{({}[()])<>(({}()[({}<({}())>)])){{}(<({}({}<({}[()])>))>)}{}<>}{}<>{}{}({}<>)>){}]{})]<(())>)(<>)]){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)}{}

açıklama

Kodun tamamını başlatmak için, yığının tepesi sıfırdan az olana kadar çalışan bir döngü vardır:

([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)
{{}
 ...
 ([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)
}{}

Döngünün içinde bölünebilirliği yedi algoritmayla çalıştırırız:

Yığının tepesini çoğalt

(({}))

Yığının tepesinin 10 modunu al (son basamak)

(<((()()()()()){}<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>({}<{}><>)

Bu biraz karışıklık ama daha sonra açıklayacağım algoritmanın geri kalanını yapıyor ama nasıl çalıştığını tam olarak hatırlamıyorum:

([(({})<([{}]{})(<((()()()()()){}(<>))>)<>{({}[()])<>(({}()[({}<({}())>)])){{}(<({}({}<({}[()])>))>)}{}<>}{}<>{}{}({}<>)>){}]{})

1

C, 56 bayt -% 75 = 14

Bu, test durumlarıyla aynı sayıları vermemesine rağmen, sorunun ruhunu (ve tartışmalı olarak daha fazlasını) karşılamaktadır. 7'nin tam katlarını doğru bir şekilde tanımlar ve diğer sayılar için tam kalanı verir (çünkü hiçbir zaman negatif sayılar kullanmaz).

n;f(char*c){for(n=0;*c;)n-=n>6?7:'0'-n-n-*c++;return n;}

Algoritmada çarpma veya bölme yoktur, sadece toplama ve çıkarma işlemleri vardır ve rakamlar soldan sağa doğru tek bir geçişte işlenir. Akümülatörde 0 ile başlayarak aşağıdaki gibi çalışır:

  1. Gerekirse 7, yine de gerekirse tekrar çıkartın
  2. Çalışan toplamı üçe katlayın ve bir sonraki rakamı ekleyin

"Üç ile çarp" adımı n-=-n-nbir bayt kaydetmek ve çarpma operatöründen kaçınmak için yazılmıştır .

Sona ulaştığımızda, yedileri çıkarmayız, bu nedenle sonuç 0-24 aralığında olacaktır; Eğer sıkı bir direnç katsayısı (0-7) isterseniz, yerine *cile *c||n>6defor döngü koşulu.

Geliştirilmiş bonusa hak kazanır, çünkü

  • isteğe bağlı tam sayıları destekler
  • giriş üzerinde soldan sağa sırayla yalnızca bir geçiş gerçekleştirir
  • alan karmaşıklığına sahiptir O (1)
  • zaman karmaşıklığına sahiptir O (n).

Test programı ve sonuçları

#include <stdio.h>
int main(int argc, char **argv) {
    while (*++argv)
        printf("%s -> %d\n", *argv, f(*argv));
    return 0;
}
540 -> 15
541 -> 16
542 -> 17
543 -> 18
544 -> 19
545 -> 20
546 -> 21
547 -> 22
548 -> 23
549 -> 24
550 -> 18
99 -> 15
999 -> 12
12345 -> 11
32767 -> 7
700168844221 -> 7
36893488147419103232 -> 11
231584178474632390847141970017375815706539969331281128078915168015826259279872 -> 11

Alternatif versiyon

İşte yinelenenlerden biri (derleyici arama dönüşümü yapmak için derleyici optimizasyonlarını etkinleştirmek isteyebilirsiniz veya yığınınızı taşabilirsiniz; kullandım gcc -std=c89 -O3):

f(c,n)char*c;{return n>6?f(c,n-7):*c?f(c+1,n+n+n+*c-'0'):n;}

İkinci argüman olarak '0' ile çağırın.

Her iki versiyon da, makinemde 50 milisaniyenin altında 60.000 basamaklı bir sayıdaki kalan modulo-yedi'yi hesaplar.


Bonus için teşekkürler - C'nin bu kadar rekabetçi kalması için gerçek bir değişiklik yapar! Şu anda sadece Jelly (11) ve Pyth (13) tarafından dövüldü . :-)
Toby Speight

1

PHP, 50 bayt

for($n=$argv[1];$n>9;)$n=$n/10|0-2*($n%10);echo$n;

alternatif çıktı kullanır; kadar çalışırPHP_INT_MAX


string sürümü, herhangi bir (pozitif) sayı (64 bayt) için çalışır:

for($n=$argv[1];$n>9;)$n=substr($n,0,-1)-2*substr($n,-1);echo$n;

0

Java, 133 bayt

int d(int n){String s=""+n;return n<71?n:d(Integer.parseInt(s.replaceFirst(".$",""))-Integer.parseInt(""+s.charAt(s.length()-1))*2);}

Ne kadar ayrıntılı Integer.parseIntolduğundan nefret ediyorum . Ungolfed:

static int div(int n) {
    if (n <= 70) {
        return n;
    } else {
        String num = ("" + n);
        int last = Integer.parseInt("" + num.charAt(num.length() - 1));
        int k = Integer.parseInt(num.replaceFirst(".$", "")) - last * 2;
        return div(k);
    }
}
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.