Mettre en œuvre la règle de divisibilité par 7

25

Pour vérifier si un nombre décimal est divisible par 7:

Effacez le dernier chiffre. Multipliez-le par 2 et soustrayez de ce qui reste. Si le résultat est divisible par 7, le nombre d'origine est divisible par 7.

(également décrit par exemple ici )

Cette règle est bonne pour le contrôle manuel de divisibilité. Par exemple:

2016 est-il divisible par 7?

Soustrayez 6*2de 201; nous obtenons 189. Est-ce divisible par 7? Pour le vérifier, appliquons à nouveau la règle.

Soustrayez 9*2de 18; nous obtenons 0. Par conséquent, 2016 est divisible par 7.

Dans ce défi, vous devez appliquer cette règle jusqu'à ce que le statut de divisibilité soit évident , c'est-à-dire que le nombre ne dépasse pas 70 (cependant, voir ci-dessous pour plus de détails). Créez une fonction ou un programme complet.

Entrée : un entier positif; votre code doit prendre en charge des entrées jusqu'à 32767 (la prise en charge d'entiers de précision arbitraire est un bonus; voir ci-dessous).

Sortie : un entier (éventuellement négatif), non supérieur à 70, résultant de l'application de la règle de divisibilité par 7 zéro ou plusieurs fois.

Cas de test:

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

Lorsque deux sorties possibles sont spécifiées, l'un ou l'autre résultat est correct: le second correspond à l'application de la règle une fois de plus. Il est interdit d'appliquer la règle sur un numéro à un chiffre: si vous effacez le chiffre, il ne reste plus rien (pas 0).


Bonus : si votre algorithme

  • Prend en charge les entiers de précision arbitraire
  • Effectue un seul passage sur l'entrée
  • A une complexité spatiale o(n)(c.-à-d. Inférieure à O(n)) et
  • A une complexité temporelle O(n),

nest le nombre de chiffres décimaux:

Soustrayez 50% du nombre d'octets de votre code.

Véritable bonus :

De plus, si votre algorithme lit l'entrée dans la direction normale, en commençant par le chiffre le plus significatif, soustrayez à nouveau 50% - votre score est de 25% de votre nombre d'octets (cela semble possible, mais je ne suis pas absolument sûr).

anatolyg
la source
1
@DenkerAffe Le retour de l'entrée telle quelle est acceptable. J'ai mis à jour le cas de test de input = 10 pour refléter cela; c'était l'idée dès le début.
anatolyg
4
Je ne voudrais pas utiliser cette règle 1000000000000000000001.
Neil
1
Mais que se passe-t-il si votre langue a un long longs ou un type équivalent intégré?
SuperJedi224 du
1
Ce que je disais, c'est que, dans certaines implémentations, c'est un entier de 128 bits, ce qui est plus que suffisant pour ce dernier cas de test.
SuperJedi224
7
-1. Toutes les langues ne prennent pas en charge la précision arbitraire.
Ho Mars

Réponses:

23

Golfscript, 27 22 octets

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

Vous pouvez l'utiliser de cette façon:

1000f

Explication

{.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'

5 octets économisés grâce à Dennis!

Dica
la source
1
Bienvenue dans Programming Puzzles et Code Golf. C'est une bonne réponse, mais vous pouvez l'améliorer en ajoutant une ventilation et une explication du code, comme les questions ci-dessus. Pour répondre à ce commentaire, tapez @wizzwizz4( @puis mon nom d'utilisateur) au début (ou n'importe où dans) un commentaire.
wizzwizz4
1
@ wizzwizz4 Mieux? Je ne suis pas sûr de comprendre ce que vous entendez par «panne de code» (pas de locuteur natif désolé)
Dica
8
Je pense que par "panne de code", il voulait dire une explication, que vous avez ajoutée. C'est une très bonne première réponse en effet. Bienvenue sur le site!
Alex A.
1
Vous pouvez réécrire la {...}{}ifpartie en tant que {...}*, ce qui appliquera simplement le bloc de code zéro une fois, selon la valeur poussée par >. De plus, nous sommes autorisés à effectuer une autre itération (donc le remplacer 70par 9enregistre un octet), et je ne pense pas que vous ayez besoin de sauter le bloc avec ;.
Dennis
3
@Dica, ceci est une première réponse suffisamment bonne pour obtenir plus de 12 votes positifs sur une question avec seulement 624 vues, et pour obtenir les éloges de deux modérateurs. Si vous continuez ainsi, vous dépasserez bientôt Dennis!
wizzwizz4
13

Haskell, 35 octets

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

Exemple d'utilisation: until(<71)(\n->div n 10-2*mod n 10) 36893488147419103232-> 32.

Rien à expliquer, c'est une implémentation directe de l'algorithme.

nimi
la source
9

Gelée, 11 octets

d⁵Uḅ-2µ>9$¿

Essayez-le en ligne!

Comment ça marche

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.
Dennis
la source
Et comme toujours, Jelly gagne. Dennis, combien d'octets faudrait-il pour implémenter un interprète Jelly dans Jelly?
Bálint
6

Python 2, 38 octets

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

Essayez-le ici !

Approche récursive simple. Imprime x si son <70 applique autrement la règle de divisibilité et s'appelle avec le résultat.

Denker
la source
vous n'avez pas besoin d'espace après le)
Maltysen
@Maltysen True. Copiez collé le mauvais, merci pour l'astuce!
Denker
2
L'if est trop verbeux. f=lambda x:x*(x<70)or f(x/10-x%10*2)
seequ
1
@Seeq Belle astuce, merci! Cela devrait fonctionner en théorie, mais il atteint la profondeur de récursivité maximale avec 2016 en entrée, contrairement à ma version. Une idée pourquoi?
Denker
Ah, c'est vrai, je n'y ai pas pensé. Cette astuce est considérée x*(x<70) != 0comme la condition de fin. Si x arrive à 0 - comme c'est le cas avec 2016 - la condition de fin ne se produit jamais.
seequ
6

Pyth, 13 octets

.W>H9-/ZTyeZQ

Essayez-le en ligne: démonstration ou suite de tests

Cela imprimera toutes les réponses alternatives.

Explication:

.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)
Jakube
la source
5

Julia, 27 26 octets

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

Il s'agit d'une fonction récursive qui accepte un entier et renvoie a BigInt. Si l'entrée est un grand nombre comme dans le dernier exemple, Julia le traite comme un BigInt, donc aucune conversion manuelle n'est nécessaire.

L'approche n'est qu'une implémentation simple de l'algorithme. Il produira les sorties alternatives. Prendre le module lors de la division par 10 donne le dernier chiffre et le quotient de la division entière par 10 donne tout sauf le dernier chiffre.

Enregistré un octet grâce à Dennis!

Alex A.
la source
Nous sommes autorisés à effectuer une autre itération, donc le remplacer 70par 9enregistre un octet.
Dennis
@Dennis Bon appel, merci!
Alex A.
4

Pyth, 17 octets

L?<b70by-/bT*%bT2

Essayez-le ici!

Même approche récursive que dans ma réponse python . Définit un lambda yqui est appelé comme ceci: y12345.
Le compteur d'octets dans l'interpréteur en ligne affiche 19 octets parce que j'y ai ajouté l'appel lambda, vous pouvez donc simplement l'essayer en appuyant sur le bouton d'exécution.

Explication

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
Denker
la source
Vous avez une faute de frappe dans votre explication, 17 devrait être 70: P
FryAmTheEggman
4

CJam - 19 octets

Version Do-while:

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

Essayez-le en ligne ou alors que la version # 1:

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

Essayez-le en ligne ou alors que la version # 2:

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

Essayez-le en ligne .

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
CJ Dennis
la source
3

Oracle SQL 11.2, 116 octets

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;

Non golfé

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;
Jeto
la source
3

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

O (1) espace, O (n) temps, passage unique!

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!)

Utilisez as 0![6,1,0,2]pour appliquer la règle à 2016, c'est-à-dire transmettez-lui d'abord un nombre sous forme de flux avec le chiffre le moins significatif. De cette façon, il passera sur le nombre chiffre par chiffre, en appliquant la règle avec la complexité d'espace O (1).

Le code non golfé est ici:

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

L'essentiel de la façon dont cela fonctionne est qu'il implémente un algorithme de soustraction chiffre par chiffre , mais tire parti du fait que chaque nombre à soustraire est au plus de 2 chiffres, et donc nous pouvons soustraire une quantité arbitraire de ces 1 - ou -2 chiffres à partir du chiffre principal (en plus de manger les chiffres les moins significatifs).

L'algorithme de soustraction est O (1) et ne stocke que la valeur d'emprunt actuelle. J'ai modifié cela pour ajouter le chiffre supplémentaire (soit 0 ou 1), et nous notons que cette valeur d'emprunt est limitée (dans la plage [-2,2], nous n'avons donc besoin que de 3 bits pour le stocker).

Les autres valeurs stockées en mémoire sont des variables temporaires représentant le nombre actuel à 2 chiffres à ajouter, une seule anticipation dans le flux et à appliquer une étape de l'algorithme de soustraction (c'est-à-dire qu'il faut deux chiffres et une valeur d'emprunt, et renvoie un chiffre et une nouvelle valeur d'emprunt).

Enfin, à la fin, il traite les deux derniers chiffres du flux à la fois pour renvoyer un numéro à un chiffre plutôt qu'une liste de chiffres.

NB La sevfonction dans la version non golfée fonctionnera sur un Integer, le convertissant en forme de flux inversé.

nitreux
la source
Je voulais que le bonus soit pour l'ordre normal des chiffres. Mais je ne l'ai jamais dit, il est donc juste d'obtenir le bonus pour l'ordre inversé, même si c'est moins amusant. Quoi qu'il en soit, même l'ordre inversé est plus difficile que je ne le pensais, donc c'est assez amusant!
anatolyg
@anatolyg: Merci! Je ne sais pas s'il est possible de faire une implémentation O (1) en un seul passage de l'ordre normal ... la règle dépend des chiffres les moins significatifs, donc en théorie l'application directe de la règle est impossible sauf dans l'ordre inverse. La seule autre chose à laquelle je peux penser est de trouver une forme mathématiquement équivalente - par exemple, Mod[18 - Quotient[n, 10] - 2*n, 21] - 18 + Quotient[n, 10]fonctionne empiriquement pour n entre 10 et 99, mais devient plus compliqué avec plus de n chiffres ...
nitreux
Hmm, j'y ai pensé et il semblait qu'il y avait un moyen de garder les 2 premiers chiffres et d'appliquer chaque chiffre suivant, mais en multipliant par (-2) ^ n pour en tenir compte 'filtrage' ... pour autant que je peut dire bien qu'il n'y ait aucun moyen de faire ce travail sans garder tous les chiffres en mémoire et sacrifier le O (1) 'ness ou même o (n)' ness ... Je pense que l'ordre normal est définitivement impossible :(
nitreux
1
Je crains que vous ne deviez également compter les octets de l'initiale 0lors de l'appel !, par exemple comme une section (0!)(+ une nouvelle ligne), c'est-à-dire +5 octets. De l'autre côté, vous pouvez raccourcir le premier pour faire correspondre les correspondances de !à p![d]=et p![d,e]=. , Modèle d'utilisation protège également au lieu de let: p!(d:e:f)|(b,a)<-quotRem(2*d)10,(q,r)<-h$e-a-p=(b+q)!(r:f).
nimi
1
@ nitreux: Oh, je mentionne (0!)sa propre ligne. (0!)est la fonction que vous donnez comme réponse. Le 0est requis, mais n'a rien à voir avec l'entrée, vous ne pouvez donc pas l'externaliser à l'appelant. Bien sûr, vous pouvez également l'utiliser f x=0!x, mais c'est plus long.
nimi
3

GNU dc, 20 15 octets

[10~2*-d70<F]sF

Ceci définit mon premier (jamais) fonction continue, F. Il prend l'entrée en haut de la pile et laisse sa sortie en haut de la pile. Exemple d'utilisation:

36893488147419103232
lFxp
32
Toby Speight
la source
2

Mathematica, 47 44 octets

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

Approche récursive simple. Pourrait probablement être joué au golf plus loin.

LegionMammal978
la source
#0[{1,-2}.QuotientRemainder[#,10]]enregistre un octet.
njpipeorgan
2

R, 43 octets

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

Explication:

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

Exemples de cycles:

> 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
Laterow
la source
1

JavaScript ES6, 38 octets

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

Les échecs avec 36893488147419103232et en utilisant ~~(1/10)échoueront également pour700168844221

Tester:

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>

andlrc
la source
Je reçois deux Fails ... 70 et 32
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Oui, je me demande toujours pourquoi ...
andlrc
Parce que le type de numéro de JavaScript ne gère pas le dernier cas, au moins.
Conor O'Brien
1
f=n=>n>70?f((n-n%10*21)/10):nest une version plus courte mais ne fonctionne toujours que jusqu'à 2**56.
Neil
@Neil voir ma réponse pour une précision arbitraire, et n'hésitez pas à jouer au golf, très apprécié.
Patrick Roberts
1

Mathematica, 33 octets

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

Cas de test

%[9999]
(* -3 *)
njpipeorgan
la source
1

Perl 5, 47 46 octets

A dû utiliser bigintpour le dernier cas de test. (Il renvoie 20 sans)

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

Pas vraiment sûr que ce soit un candidat pour le bonus, donc je ne l'ai pas pris en compte. (Je pense que oui, mais je ne suis pas vraiment habitué aux concepts)

Essayez-le ici!

Paul Picard
la source
1

ES6, 108 octets

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

Fonctionne pour 2²⁵⁷ et 1000000000000000000001, mais pourrait utiliser davantage de golf.

Neil
la source
@PatrickRoberts Oups, supervision lors du reformatage de la soumission.
Neil
1

JavaScript ES6, 140 142 octets

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

Il s'agit de véritables mathématiques de précision arbitraire, qui fonctionnent même sur le plus grand cas de test.

Cette fonction supprime récursivement le dernier chiffre de la chaîne, puis soustrait 2 * le dernier chiffre de la chaîne numérique restante en incrémentant de manière itérative le nombre de chiffres à appliquer au minuend jusqu'à ce que la différence soit positive. Ensuite, il ajoute cette différence à la fin de la chaîne avec des 0s correctement remplis et s'appelle récursivement jusqu'à ce que sa valeur numérique soit inférieure ou égale à 9.

  • Golfé 7 octets grâce à @Neil (oui je sais que j'ai gagné 2 octets mais j'ai corrigé quelques bugs qui provoquaient le blocage de la fonction ou renvoyaient une mauvaise sortie dans certains cas).

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>`))

Patrick Roberts
la source
Bien, mais cela pourrait ne pas fonctionner 1000000000000000000001.
Neil
1
Essayez s.replace(/.$/,'-$&*2'). Je n'ai pas d'idées évidentes pour le reste mais désolé.
Neil
1

C #, 111 104 octets

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);}
TheLethalCoder
la source
1

Brain-Flak , 368 360 octets

Essayez-le en ligne!

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

Explication

Pour commencer, tout le code est dans une boucle qui s'exécute jusqu'à ce que le haut de la pile soit inférieur à zéro:

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

À l'intérieur de la boucle, nous exécutons l'algorithme divisible par sept:

Dupliquez le haut de la pile

(({}))

Prenez le mod 10 du haut de la pile (dernier chiffre)

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

C'est un peu compliqué, mais il fait le reste de l'algorithme, je pourrais l'expliquer plus tard, mais je ne me souviens pas entièrement comment cela fonctionne:

([(({})<([{}]{})(<((()()()()()){}(<>))>)<>{({}[()])<>(({}()[({}<({}())>)])){{}(<({}({}<({}[()])>))>)}{}<>}{}<>{}{}({}<>)>){}]{})
Assistant de blé
la source
1

C, 56 octets - 75% = 14

Bien que cela ne donne pas exactement les mêmes chiffres que les cas de test, cela satisfait l'esprit de la question (et sans doute plus). Il identifie correctement les multiples exacts de 7 et donne le reste exact pour les autres nombres (car il n'utilise jamais de nombres négatifs).

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

Il n'y a pas de multiplication ou de division dans l'algorithme, seulement l'addition et la soustraction, et les chiffres sont traités en un seul passage de gauche à droite. Cela fonctionne comme suit, en commençant par 0 dans l'accumulateur:

  1. Soustrayez 7 si nécessaire, et encore si toujours nécessaire
  2. Multipliez le total cumulé par trois et ajoutez le chiffre suivant

L'étape "multiplier par trois" est écrite de manière n-=-n-nà enregistrer un octet et à éviter l'opérateur multiplier.

Lorsque nous atteignons la fin, nous ne soustrayons pas les sept, donc le résultat sera compris entre 0 et 24; si vous voulez un module strict (0-7), remplacez-le *cpar *c||n>6dans la forcondition de boucle.

Il se qualifie pour le bonus amélioré, car il

  • prend en charge les entiers de précision arbitraire
  • effectue une seule passe sur l'entrée, de gauche à droite
  • a une complexité spatiale O (1)
  • a la complexité temporelle O (n).

Programme et résultats des tests

#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

Version alternative

En voici une qui se reproduit (vous voudrez activer les optimisations du compilateur pour faire une transformation d'appel de queue ou vous pouvez déborder votre pile; j'ai utilisé 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;}

Appelez-le avec «0» comme deuxième argument.

Les deux versions calculent le reste-modulo-sept d'un nombre de 60 000 chiffres en moins de 50 millisecondes sur ma machine.

Toby Speight
la source
Merci pour le bonus - cela fait un vrai changement pour que C devienne si compétitif! Actuellement battu uniquement par Jelly (11) et Pyth (13). :-)
Toby Speight
1

PHP, 50 octets

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

utilise une sortie alternative; fonctionne jusqu'àPHP_INT_MAX


version chaîne, fonctionne pour n'importe quel nombre (positif) (64 octets):

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

Java, 133 octets

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

Je déteste la verbosité Integer.parseInt. Non golfé:

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);
    }
}
Justin
la source