Diviser un nombre par 3 sans utiliser d'opérateurs *, /, +, -,%

48

En citant cette question sur SO (alerte spoiler!):

Cette question a été posée dans une interview avec Oracle.

Comment diviseriez-vous un nombre par 3 sans utiliser *, /, +, -,%, opérateurs?

Le numéro peut être signé ou non signé.

La tâche peut être résolue, mais voyez si vous pouvez écrire le code le plus court.

Règles:

  • Effectuer la division entière requise ( /3)
  • Ne pas utiliser les opérateurs non basés sur le texte *, /, +, -ou %(ou leurs équivalents, par exemple __div__ou add()). Ceci s'applique également aux opérateurs d'incrémentation et de décrémentation, tels que i++ou i--. L'utilisation d'opérateurs pour la concaténation de chaînes et le formatage est correcte. L'utilisation de ces caractères pour différents opérateurs, tels que l' -opérateur unaire pour les nombres négatifs, ou *pour représenter un pointeur en C est également acceptable.
  • La valeur d'entrée peut être arbitrairement grande (tout ce que votre système peut gérer), à la fois positive et négative
  • L'entrée peut être sur STDIN ou ARGV ou entrée d'une autre manière
  • Créez le code le plus court possible pour faire ce qui précède
Gaffi
la source
1
Comment arrondir le résultat quand il est positif? Comment quand négatif?
dfeuer

Réponses:

15

J, 45 44 10 caractères

".,&'r3'":

Fonctionne avec des négatifs:

".,&'r3'": 15
5
   ".,&'r3'": _9
_3
   ".,&'r3'": 3e99
1e99

": - formater en texte

,&'r3'- ajouter r3à la fin

". - exécuter la chaîne, par exemple 15r3

defhlt
la source
1
Cela fonctionne si vous le faites 3 3 3 #: 9. Il semble que vous ayez besoin de savoir combien de temps votre numéro ternaire sera. _3]\i.est également un point de départ possible pour quelque chose, mais je ne sais pas si ce serait plus court que votre solution ici. Le problème avec #_3]\i.ce qu'il est, c'est qu'il arrondit toujours au lieu de tomber.
Gareth
1
Peut-être ##~3=_3#\i.pour 11 personnages?
Gareth
1
En fait, vous pouvez réduire votre nombre à 10 avec ##~0 0 1$~.
Gareth
1
Vous pouvez réduire cela à l’aide d’un crochet, 3#.}:(#:~$&3)mais cela reste plus long et cela ne résout pas le problème du nombre négatif.
Gareth
1
Oui, vous pouvez utiliser la fonction Power ^: ou Agenda @. pour un remplacement ifou un if...elseremplacement. Dans ce cas, vous pouvez utiliser @.deux verbes associés à un caractère '' '(un gérondif en j-speak) pour sélectionner l'un ou l'autre en fonction d'une condition.
Gareth
56

C, 167503724710

Voici ma solution au problème. J'admets qu'il est peu probable de gagner une compétition de golf au code strict, mais il n'utilise aucune astuce pour appeler indirectement la fonctionnalité de division intégrée, il est écrit en C portable (comme la question originale de Stack Overflow demandée), il fonctionne parfaitement. pour les nombres négatifs, et le code est exceptionnellement clair et explicite.

Mon programme est la sortie du script suivant:

#!/usr/bin/env python3
import sys

# 71
sys.stdout.write('''#include <stdint.h>
#include <stdio.h>
int32_t div_by_3(int32_t input){''')

# 39 * 2**32
for i in range(-2**31, 2**31):
    # 18 + 11 + 10 = 39
    sys.stdout.write('if(input==%11d)return%10d;' % (i, i / 3))

# 95
sys.stdout.write(r'''return 7;}int main(int c,char**v){int32_t n=atoi(a[1]);printf("%d / 3 = %d\n",n, div_by_3(n));}''')

Nombre de caractères: 71 + 39 * 2 ** 32 + 95 = 167503724710

Des repères

Il a été demandé combien de temps cela prendrait et combien de mémoire il utiliserait, alors voici quelques points de repère:

  • Durée d'exécution du script - Une exécution ./test.py | pv --buffer-size=1M --average-rate > /dev/nulld'environ 30 secondes génère un débit d'environ 14,8 Mo / s. On peut raisonnablement supposer que le taux de sortie est à peu près constant, le temps d’exécution devrait donc être d’environ 167503724710 B / (14,8 * 1048576 B / s) ≈ 10794 s.
  • Temps de compilation - Le compilateur TCC prétend compiler le code C à 29,6 Mo / s , soit un temps de compilation de 167503724710 B / (29,6 * 1048576 B / s) ≈ 5397 s. (Bien sûr, cela peut fonctionner dans un pipeline avec le script.)
  • Taille du code compilé - j’ai essayé de l’estimer en utilisant ./test.py | tcc -c - -o /dev/stdout | pv --buffer-size=1M --average-rate > /dev/null, mais il semble tccque rien ne soit sorti tant qu’il n’a pas lu le fichier source complet
  • Utilisation de la mémoire pour s'exécuter - Puisque l'algorithme est linéaire (et que tcc n'optimise pas sur plusieurs lignes), la surcharge de la mémoire ne devrait être que de quelques kilo-octets (hormis le code lui-même, bien sûr).
Escargot mécanique
la source
22
C'est la quintessence du codage en dur. ++++++++++
Joe Z.
4
Cela dit, je suis sûr que si vous leur fournissiez un fichier source de 160 Go et leur demandiez de le compiler et de le tester, ils vous regarderaient comme si vous étiez fou.
Joe Z.
16
Si mon patron me demandait de calculer une division par trois sans - + / *%, je penserais qu'il est fou.
Mikaël Mayer
Et pourtant, a[b]est un sucre syntaxique pour *(a + b), qui fait l'addition.
Konrad Borowski
12
@NicolasBarbulesco Il existe une restriction de taille pour les réponses Stack Exchange.
Timtech
38

Ruby 28

b=->n{n.to_s(3).chop.to_i 3}

Pour diviser par 3, il suffit de supprimer le zéro final en base 3: 120 -> 11110 -> 1111 -> 40

Fonctionne avec des négatifs:

ice distantstar:~/virt/golf [349:1]% ruby ./div3.rb
666
222
ice distantstar:~/virt/golf [349]% ruby ./div3.rb
-15        
-5

Rubis, 60 45

Sinon, sans utiliser la conversion de base:

d = -> n {x = n.abs; r = (0..1.0 / 0) .phase (3) .take (x) .index x; n> 0? r: -r}

d=->n{(r=1.step(n.abs,3).to_a.size);n>0?r:-r}
defhlt
la source
1
Le remplacement sans conversion de base a l' /opérateur banni où Float::INFINITYest devenu 1.0/0. Avec Ruby 2.1, on peut jouer (0..1.0/0).step(3)au golf en 0.step(p,3)supprimant le /. Le plus gros problème est que -rutilise -pour nier. Il faut 5 caractères pour passer -rà ~r.pred, abusant d' Integer # avant de soustraire 1 sans l'opérateur de soustraction.
Kernigh
26

Mathematica, 13 caractères

Mean@{#,0,0}&
Alephalpha
la source
C’est méchant: je suppose que vous pourriez sauvegarder le &et utiliser une variable simple (d’autres le font aussi).
Yves Klett
3
@YvesKlett: La moyenne est intrinsèquement mauvaise.
GuitarPicker
18

JavaScript, 56

alert(Array(-~prompt()).join().replace(/,,,/g,1).length)

Crée une chaîne de longueur nde répétition ,s et remplace ,,,par 1. Ensuite, il mesure la longueur résultante de la chaîne. (Espérons que le unaire -est autorisé!)

Casey Chu
la source
+1 mais cela ne fonctionne pas avec des valeurs négatives
Francesco Casula
Euh, question ... comment ça compte? Il utilise l' -opérateur de négation.
Patrick Roberts
@ Patrick j'ai pris la spécification pour signifier aucune soustraction - si vous voulez, vous pouvez remplacer -~parparseInt()
Casey Chu
@CaseyChu, la valeur renvoyée par -~prompt()est supérieure à parseInt(prompt()). Je ne sais pas comment vous allez gérer ça.
Patrick Roberts
alert(Array(parseInt(prompt())).slice(1).join().replace(/,,,/g,1).length)
Casey Chu
16

Python, 41 38

print"-"[x:]+`len(xrange(2,abs(x),3))`

xrange semble être capable de gérer de grands nombres (je pense que la limite est la même que pour un long en C) presque instantanément.

>>> x = -72
-24

>>> x = 9223372036854775806
3074457345618258602
grc
la source
2
10/3égale 3, pas 4.
Joel Cornett
Faire print" -"[x<0]+len (range (2, abs (x), 3)) `` le réduira à 39 caractères
Joel Cornett
Le formatage des commentaires de golfexchange est en train de tout gâcher. sur ce qui précède, j’ai utilisé des pics pour len()en faire un raccourci pourrepr()
Joel Cornett
Je l'ai mis à jour. Je ne peux pas utiliser range, car cela va créer la liste. xrangefait semblant, alors il est capable de gérer des nombres énormes sans perdre de temps / mémoire.
grc
2
Imaginez que c'est Python 3;) J'aime le découpage de caractère unique.
Joel Cornett
11

Haskell, 90 106

d n=snd.head.dropWhile((/=n).fst)$zip([0..]>>=ν)([0..]>>=replicate 3>>=ν);ν q=[negate q,q]

Crée une liste de recherche infinie (lazy) [(0,0),(0,0),(-1,0),(1,0),(-2,0),(2,0),(-3,-1),(3,1), ...], supprime tous les éléments qui ne correspondent pas n( /=c'est l'inégalité dans Haskell) et renvoie le premier qui le correspond.

Cela devient beaucoup plus simple s'il n'y a pas de nombre négatif:

25 27

(([0..]>>=replicate 3)!!)

renvoie simplement le nthème élément de la liste [0,0,0,1,1,1,2, ...].

a cessé de tourner dans le sens antihoraire
la source
3
oO je n'ai jamais pensé à cette deuxième solution. Je pourrais être capable d'implémenter quelque chose comme ça en python
acolyte
8

C #, 232 octets

Mon premier code golf ... Et comme il n'y avait pas de C # et que je voulais essayer une méthode différente de celle que nous n'avions pas essayée ici, j'ai pensé tenter le coup. Comme certains autres ici, seuls les nombres non négatifs.

class l:System.Collections.Generic.List<int>{}class p{static void Main(string[] g){int n=int.Parse(g[0]);l b,a=new l();b=new l();while(a.Count<n)a.Add(1);while(a.Count>2){a.RemoveRange(0,3);b.Add(1);}System.Console.Write(b.Count);}}

Ungolfed

class l : System.Collections.Generic.List<int>
{ }
class p
{
    static void Main(string[] g)
    {
        int n = int.Parse(g[0]);
        l b, a = new l();
        b = new l();
        while (a.Count < n) a.Add(1);
        while (a.Count > 2)
        {
            a.RemoveRange(0, 3);
            b.Add(1);
        }
        System.Console.Write(b.Count);
    }
}
Drake Clarris
la source
2
Environ 5 ans plus tard .. Vous pouvez économiser 1 octet en supprimant l'espace en le string[] gtransformant enstring[]g
Metoniem
Citant "N'utilisez pas les opérateurs non textuels *, /, +, - ou% (ou leurs équivalents, tels que div ou add ()" - n'utilisez-vous pas un équivalent - .Add?
Jonathan Frech
@JonathanFrech Cette méthode d'ajout ne fonctionne pas sur deux nombres, elle ajoute seulement une valeur à une collection
Incarnation of Ignorance
7

Perl (26 22)

$_=3x pop;say s|333||g

Cette version (ab) utilise le moteur de regex de Perl. Il lit un nombre en dernier argument de la ligne de commande ( pop) et construit une chaîne de 3s de cette longueur ( "3" x $number). L'opérateur de substitution de regex ( s///écrit ici avec des délimiteurs différents en raison des règles du puzzle et d'un gdrapeau lobal) remplace trois caractères par la chaîne vide et renvoie le nombre de substitutions, qui est le nombre entier divisé par trois. Il pourrait même être écrit sans 3, mais la version ci-dessus semble plus drôle.

$ perl -E '$_=3x pop;say s|333||g' 42
14
memowe
la source
2
Hey @memowe, beau travail! Vous pouvez économiser quelques caractères supplémentaires (4) en faisant $_=3x pop;say s|333||g.
Dom Hastings
2
Lorsque l'entrée est 0, 1 ou 2, une chaîne vide est imprimée. Si elle a besoin d'imprimer 0, il a besoin de 3 caractères plus (25 au total): '$_=3x pop;say s|333||g||0. Lent avec de grands nombres comme 99999999 et ne fonctionne pas avec des nombres négatifs.
kernigh
1
Utilisez -psur la ligne de commande, et vous pouvez faire: $_=3x$_;$_=0|s|...||gpour un total de 22, y compris la couverture des entrées 0, 1 ou 2.
Xcali
6

C, 160 caractères

Solution de division longue caractère par caractère en utilisant des tables de correspondance, c'est-à-dire sans chaîne atoi () ou printf () pour convertir entre des chaînes de base 10 et des entiers.

La sortie comprendra parfois un zéro non significatif - une partie de son charme.

main(int n,char**a){
char*s=a[1],*x=0;
if(*s==45)s=&s[1];
for(;*s;s=&s[1])n=&x[*s&15],x="036"[(int)x],*s=&x["000111222333"[n]&3],x="012012012012"[n]&3;
puts(a[1]);
}

Remarque:

  • abuse de l'accès au tableau pour implémenter l'ajout
  • compile avec clang 4.0, d’autres compilateurs peuvent faire des dégâts.

Essai:

./a.out -6            -2
./a.out -5            -1
./a.out -4            -1
./a.out -3            -1
./a.out -2            -0
./a.out -1            -0
./a.out 0             0
./a.out 1             0
./a.out 2             0
./a.out 3             1
./a.out 4             1
./a.out 5             1
./a.out 6             2
./a.out 42            14
./a.out 2011          0670
bébé-lapin
la source
6

Python 42

int(' -'[x<0]+str(len(range(2,abs(x),3))))

Puisque chaque solution postée ici que j’ai vérifiée tronque les décimales, voici ma solution.

Python 50 51

int(' -'[x<0]+str(len(range([2,0][x<0],abs(x),3))))

Puisque python fait la division du sol, voici ma solution qui implémente cela.

Le nombre entier d'entrée est dans la variable x.

Testé en Python 2.7 mais je suppose que cela fonctionne également en version 3.

Mat
la source
+1 Pour offrir les deux alternatives à la situation de valeur négative. Comme il y a déjà tellement de réponses, je ne modifierai pas les spécifications pour exclure l'une ou l'autre des options, bien que je convienne personnellement que -3c'est la bonne réponse -10/3.
Gaffi
Pour ceux qui se soucient de la division du sol en python: python-history.blogspot.com/2010/08/…
Matt
Qu'en est-il de la multiplication et de la soustraction dans votre deuxième solution?
Boothby
@boothby La deuxième solution implémente la division du sol. Je voulais faire la plage (0, abs (x), 3) pour les nombres négatifs et la plage (2, abs (x), 3) pour les nombres positifs. Afin de faire cela j'avais gamme (2 ... alors je soustrais 2 quand x est négatif. X <0 est vrai quand x est négatif, (vrai) * 2 == 2
Matt
Je ne comprends pas la différence entre la division du sol et les décimales tronquées. Est-ce que cela doit avec une division négative?
Joel Cornett
6

JavaScript, 55

alert(parseInt((~~prompt()).toString(3).slice(0,-1),3))

Si on ne peut pas utiliser -1, alors voici une version qui la remplace par ~0(merci Peter Taylor!).

alert(parseInt((~~prompt()).toString(3).slice(0,~0),3))
Inkbug
la source
1
@ArtemIce One ~est un opérateur Bitwise qui inverse les bits de l'opérande (le convertissant d'abord en un nombre). C'est le moyen le plus rapide de convertir une chaîne en nombre (pour autant que je sache).
Inkbug
1
J'ai l'impression qu'utiliser l'analyse et la conversion des chaînes est une tricherie, car a) c'est un processus très compliqué et coûteux par rapport aux opérations au niveau des bits, b) utilise les opérateurs interdits en interne et c) prendrait plus de caractères qu'une solution homeroll. Un peu comme la façon dont les gens deviennent grincheux lorsque vous utilisez les tris intégrés lorsque vous êtes invité à mettre en œuvre un tri rapide.
Wug
1
@ Sam En outre, ~~convertit en un entier, par opposition à +.
Inkbug
1
@Wug C'est codegolf, donc il ne s'agit pas d'efficacité sauf si spécifié dans la tâche.
defhlt
3
+1 pour profiter de différentes bases. C'est l'une de mes techniques de golf JavaScript préférées.
DocMax
6

C 83 caractères

Le nombre à diviser est passé par stdin et il le renvoie comme code de sortie de main()(% ERRORLEVEL% dans CMD). Ce code constitue une utilisation abusive de certaines versions de MinGW dans la mesure où, lorsque les optimisations ne sont pas activées, il traite la dernière valeur d’assignation comme une instruction return. Il peut probablement être réduit un peu. Prend en charge tous les nombres pouvant s’intégrer à unint

Si unaire nier (-) n'est pas autorisé: (129)

I(unsigned a){a=a&1?I(a>>1)<<1:a|1;}main(a,b,c){scanf("%i",&b);a=b;a=a<0?a:I(~a);for(c=0;a<~1;a=I(I(I(a))))c=I(c);b=b<0?I(~c):c;}

Si unaire nier est IS autorisé: (123)

I(unsigned a){a=a&1?I(a>>1)<<1:a|1;}main(a,b,c){scanf("%i",&b);a=b;a=a<0?a:-a;for(c=0;a<~1;a=I(I(I(a))))c=I(c);b=b<0?-c:c;}

EDIT: Ugoren m'a fait remarquer que - ~ est un incrément ...

83 caractères si la négation unaire est autorisée: D

main(a,b,c){scanf("%i",&b);a=b;a=a<0?a:-a;for(c=0;a<~1;a=-~-~-~a)c=-~c;b=b<0?-c:c;}
Kaslai
la source
Si négation unaire est autorisée, x+3est -~-~-~x.
Ugoren
Merci pour ça. Je ne sais pas pourquoi cela ne m'est jamais arrivé. Je suppose que je n'avais pas réalisé que vous pouviez empiler des unaires si gratuitement, hehe.
Kaslai
5

C, 139 caractères

t;A(a,b){return a?A((a&b)<<1,a^b):b;}main(int n,char**a){n=atoi(a[1]);for(n=A(n,n<0?2:1);n&~3;t=A(n>>2,t),n=A(n>>2,n&3));printf("%d\n",t);}

Exécuter avec un nombre comme argument de ligne de commande

  • Gère les nombres négatifs et positifs

Essai:

 ./a.out -6            -2
 ./a.out -5            -1
 ./a.out -4            -1
 ./a.out -3            -1
 ./a.out -2            0
 ./a.out -1            0
 ./a.out 0             0
 ./a.out 1             0
 ./a.out 2             0
 ./a.out 3             1
 ./a.out 4             1
 ./a.out 5             1
 ./a.out 6             2
 ./a.out 42            14
 ./a.out 2011          670

Modifications:

  • enregistré 10 caractères en mélangeant l'addition (A) pour supprimer les variables locales.
bébé-lapin
la source
1
Bien fait. J'ai fait de mon mieux au moment de tourner un peu et j'ai atteint 239. Je n'arrive pas à comprendre ce que vous dites A, ma fonction vérifie simplement le bit i du numéro n. Est-ce que C standard autorise l’omission de déclarations de type ou est-ce quelque chose de compilateur?
Shiona
1
C assumera int si non spécifié.
Wug
5

ZSH - 31 20/21

echo {2..x..3}|wc -w

Pour les nombres négatifs:

echo {-2..x..3}|wc -w

Avec des nombres négatifs (ZSH + bc) -62 61

Je ne devrais probablement pas donner ma réponse à deux programmes. Alors, voici un programme qui fonctionne pour tout signe de nombre:

echo 'obase=10;ibase=3;'`echo 'obase=3;x'|bc|sed 's/.$//'`|bc

Ceci utilise le même truc de conversion de base que la réponse d'Artem Ice .

Jon Gauthier
la source
5

C, 81 73 caractères

Prend en charge uniquement les nombres non négatifs.

char*x,*i;
main(){
    for(scanf("%d",&x);x>2;x=&x[~2])i=&i[1];
    printf("%d",i);
}

L'idée est d'utiliser l'arithmétique de pointeur. Le nombre est lu dans le pointeur x, ce qui ne pointe nulle part. &x[~2]= &x[-3]= x-3est utilisé pour soustraire 3. Ceci est répété tant que le nombre est supérieur à 2. icompte le nombre de fois que cela est fait ( &i[1]= i+1).

Ugoren
la source
En essayant de comprendre le code, quelqu'un a jeté des lumières? Merci
Cong Hui
@Chui, ajout d'une explication.
ugoren
Pour autant que je sache, @ugoren, printf ("% d") ne devrait-il pas imprimer le pointeur d’adresse mémoire que j’ai en Hex? pourquoi il imprime un entier? ou car * i a été initialisé pour pointer sur l'adresse de mémoire 0 par défaut? Merci
Cong Hui
5

Java 86 79

Supposons que l'entier est dans y:

Convertit en chaîne en base 3, supprime le dernier caractère (décalage droit ">>" en base 3), puis reconvertit en entier.

Fonctionne pour les nombres négatifs.

Si le nombre, y, est <3 ou> -3, il donne 0.

System.out.print(~2<y&y<3?0:Long.valueOf(Long.toString(y,3).split(".$")[0],3));

Première publication sur code golf. =) Donc, je ne peux pas encore commenter.

Thx Kevin Cruijssen pour les conseils.

Vectorisé
la source
Je sais que cela fait plus de deux ans, mais vous pouvez jouer au golf en plusieurs parties: &&à &et 2x Integerà Long. (Aussi, pourquoi utilisez-vous ~2au lieu de juste -3? Ce sont le même nombre d'octets.)
Kevin Cruijssen
1
@KevinCruijssen Si nostalgique d'éditer mon premier post après si longtemps. Je ne savais pas trop pourquoi je pensais que ~ 2 était mieux à l'époque.
Vectorisé
2
@KevinCruijssen, le défi dit que vous n'êtes pas autorisé à utiliser -, mais je ne sais pas si cela compte pour la négation unaire.
FlipTack
@ FlipTack Ah, tu as tout à fait raison. Dans ce cas, oublie ce que je t'ai déjà dit. :)
Kevin Cruijssen
4

Python2.6 ( 29 ) ( 71 ) ( 57 ) ( 52 ) (43)

z=len(range(2,abs(x),3))
print (z,-z)[x<0]

print len(range(2,input(),3))

Edit - Je viens de me rendre compte que nous devons aussi gérer les entiers négatifs. Va réparer ça plus tard

Edit2 - Fixe

Edit3 - Sauvegardé 5 caractères en suivant les conseils de Joel Cornett

Edit4 - Etant donné que l'entrée ne doit pas nécessairement provenir de STDIN ou d'ARGV, enregistrez 9 caractères en ne prenant aucune entrée de stdin

elssar
la source
Allez-y avecabs()
jeudi
plus court à faireprint z if x==abs(x) else -z
Joel Cornett
Mieux encore,print (z,-z)[x<0]
Joel Cornett
@ArtemIce merci, j'ai seulement réalisé que je pouvais l'utiliser après avoir lu une autre réponse ci-dessus.
elssar
@JoelCornett humm, je ne le savais pas, merci
elssar
4

Javascript, 47 29

Utilise evalpour générer dynamiquement a /. Utilisé +uniquement pour la concaténation de chaînes, pas pour l'addition.

alert(eval(prompt()+"\57"+3))

EDIT: Utilisé "\57"au lieu deString.fromCharCode(47)

Peter Olson
la source
-1 pour alert(eval(prompt()+"\573"))?
Shieru Asakoto le
4

Rubis ( 43 22 17)

Non seulement le golf, mais l'élégance aussi :)

p Rational gets,3

La sortie sera comme (41/1). Si ce doit être un entier, nous devons ajouter .to_iau résultat, et si nous passons to_ià, to_fnous obtiendrons également une sortie pour les floats.

Hauleth
la source
1
Fonctionne sans la rationalligne require sur Ruby 1.9.3. L'omission des parenthèses enregistre un caractère supplémentaire .
steenslag
4

TI-Basic, 8 octets

Gagnant? :)

int(mean({Ans,0,0

PS arrondit vers l'infini pour les nombres négatifs (voir ici pourquoi). Pour arrondir à zéro à la place, remplacez-le int(par iPart(aucun changement d'octet.

Cas de test

-4:prgmDIVIDE
              -2
11:prgmDIVIDE
               3
109:prgmDIVIDE
              36
Timtech
la source
3

Python 2.x, 54 53 51

print' -'[x<0],len(range(*(2,-2,x,x,3,-3)[x<0::2]))

_est le dividende et est inscrit comme tel.

>>> x=-19
>>> print' -'[x<0],len(range(*(2,-2,x,x,3,-3)[x<0::2]))
- 6

Remarque: Vous ne savez pas si l'utilisation de l'interpréteur interactif est autorisée, mais selon l'OP: "L'entrée peut être sur STDIN ou ARGV ou être entrée de toute autre manière"

Edit: Maintenant pour python 3 (fonctionne en 2.x, mais affiche un tuple). Fonctionne avec des négatifs.

Joel Cornett
la source
Fonctionne également en python 3?
Escargot mécanique
Ne doit pas nécessairement être souscrit; avoir __len__suffit.
Escargot mécanique
len(range(100,1000))donne 900en 3.2.3 sur linux.
Escargot mécanique
Cela ne fonctionne pas pour les nombres négatifs. Et len(xrange(0,_,3))est plus courte et massivement plus rapide de toute façon.
grc
@Mechanicalsnail: Point pris. Je concède. Ca marche 3.
Joel Cornett
3

C ++, 191

Avec les caractères principaux et inclus, ses 246, sans les éléments principaux et non compris, ce n’est que 178. Les nouvelles lignes comptent pour 1 caractère. Traite tous les nombres comme non signés. Je ne reçois pas d'avertissement pour que main retourne un int non signé, donc c'est juste.

Ma toute première soumission de codegolf.

#include<iostream>
#define R return
typedef unsigned int U;U a(U x,U y){R y?a(x^y,(x|y^x^y)<<1):x;}U d(U i){if(i==3)R 1;U t=i&3,r=i>>=2;t=a(t,i&3);while(i>>=2)t=a(t,i&3),r=a(r,i);R r&&t?a(r,d(t)):0;}U main(){U i;std::cin>>i,std::cout<<d(i);R 0;}

utilise des décalages pour diviser le nombre par 4 de manière répétée et calcule la somme (qui converge vers 1/3)

Pseudocode:

// typedefs and #defines for brevity

function a(x, y):
    magically add x and y using recursion and bitwise things
    return x+y.

function d(x):
    if x = 3:
        return 1.
    variable total, remainder
    until x is zero:
        remainder = x mod 4
        x = x / 4
        total = total + x
    if total and remainder both zero:
        return 0.
    else:
        return a(total, d(remainder)).

En passant, je pourrais éliminer la méthode main en nommant d main et en lui faisant prendre un caractère ** et en utilisant la valeur renvoyée par les programmes comme sortie. Il renverra le nombre d'arguments de la ligne de commande divisé par trois, arrondi au chiffre inférieur. Cela apporte sa longueur au 191 annoncé:

#define R return
typedef unsigned int U;U a(U x,U y){R y?a(x^y,(x|y^x^y)<<1):x;}U main(U i,char**q){if(i==3)R 1;U t=i&3,r=i>>=2;t=a(t,i&3);while(i>>=2)t=a(t,i&3),r=a(r,i);R r&&t?a(r,d(t)):0;}
Wug
la source
3

Golfscript - 13 caractères

~3base);3base
gnibbler
la source
ne semble pas gérer les entrées négatives
res
1
@res s/seem to //:(. Je vais devoir y réfléchir
gnibbler
3

PowerShell 57 ou 46

Dans 57 caractères utilisant %comme opérateur PowerShell foreach, pas modulo. Cette solution peut accepter des entiers positifs ou négatifs.

(-join(1..(Read-Host)|%{1})-replace111,0-replace1).Length

En 46 caractères, si *est autorisé en tant qu'opérateur de répétition de chaîne, ne pas multiplier. Cette option nécessite des entiers positifs en tant que valeurs d'entrée.

("1"*(Read-Host)-replace111,0-replace1).Length
Joseph Alcorn
la source
Si jamais vous revenez, j'ai posté un correctif de bogue. Si vous voulez que je supprime le mien et que j'intègre le changement dans le vôtre, faites le moi savoir.
Veskah
3

R

Ceux-ci ne fonctionnent qu'avec des entiers positifs:

max(sapply(split(1:x,1:3), length))
# Gives a warning that should be ignored

Ou:

min(table(rep(1:3, x)[1:x]))

Ou:

length((1:x)[seq(3,x,3)])

Ou:

sum(rep(1,x)[seq(3,x,3)])

[[EDIT]] Et un vilain:

trunc(sum(rep(0.3333333333, x)))

[[EDIT2]] Plus probablement le meilleur - inspiré du code matlab ci-dessus par Elliot G:

length(seq(1,x,3))
lebatsnok
la source
Je voulais mettre en œuvre la même idée que dans votre EDIT2 mais cela ne fonctionne pas pour les nombres négatifs:wrong sign in 'by' argument
Andreï Kostyrka
3

SmileBASIC, 58 51 36 octets (pas de fonctions mathématiques!)

INPUT N
BGANIM.,4,-3,N
WAIT?BGROT(0)

Explication:

INPUT N           'get input
BGANIM 0,"R",-3,N 'smoothly rotate background layer 0 by N degrees over 3 frames
WAIT              'wait 1 frame
PRINT BGROT(0)    'display angle of layer 0

Le programme déplace le calque d'arrière-plan en douceur sur 3 images, puis obtient l'angle après 1 image lorsqu'il a parcouru 1/3 de sa distance totale.

Version de la division float, 38 octets:

INPUT N
BGANIM.,7,-3,N
WAIT?BGVAR(0,7)

Explication:

INPUT N           'input
BGANIM 0,"V",-3,N 'smoothly change layer 0's internal variable to N over 3 frames
WAIT              'wait 1 frame
PRINT BGVAR(0,7)  'display layer 0's internal variable
12Me21
la source
3

Haskell 41 39 caractères

Fonctionne avec tous les entiers positifs et négatifs

f n=sum[sum$1:[-2|n<0]|i<-[3,6..abs n]]

Crée d’abord une liste de 1 ou (-1) (selon le signe de l’entrée) pour chaque troisième entier compris entre 0 et 0 n. abs(n)pour les nombres négatifs inclus.

par exemple n=8 -> [0,3,6]

Il retourne ensuite la somme de cette liste.

Charl Kruger
la source
Ne fonctionne pas sur les nombres négatifs (-3/3 est -1 et non 1).
Cormac le
Bien, vous avez réussi à faire fonctionner les nombres négatifs, mais vous ne pouvez pas utiliser /, lisez la spécification.
Cormac le
Oh ça alors, tu m'as deux fois. Tous fixes;)
Charl Kruger le
Agréable! Btw Vous pouvez obtenir 39 caractères avec fn = sum [somme $ 1: [- 2 | n <0] | i <- [3,6..abs n]]
Cormac
2

Clojure, 87; fonctionne avec des négatifs; basé sur des lazyseqs

(defn d[n](def r(nth(apply interleave(repeat 3(range)))(Math/abs n)))(if(> n 0)r(- r)))

Ungolfed:

(defn d [n]
  (let [r (nth (->> (range) (repeat 3) (apply interleave))
               (Math/abs n))]
        (if (pos? n)
          r
          (- r))))
defhlt
la source