Compter les diviseurs d'un nombre


26

introduction

C'est un défi très simple: il suffit de compter les diviseurs d'un nombre. Nous avons eu un défi similaire mais plus compliqué auparavant, mais j'ai l'intention que celui-ci soit d'entrée de gamme.

Le défi

Créez un programme ou une fonction qui, étant donné un entier strictement positif N, génère ou renvoie le nombre de diviseurs dont il dispose, y compris 1 et N.

Entrée: Un entier> 0. Vous pouvez supposer que le nombre peut être représenté dans le type numérique natif de votre langue.

Sortie: le nombre de diviseurs entiers positifs qu'il possède, y compris 1 et le nombre lui-même.

Les soumissions seront notées en octets . Vous pouvez trouver ce site Web à portée de main, mais vous pouvez utiliser toute méthode raisonnable pour générer votre nombre d'octets.

C'est le , donc le score le plus bas gagne!

Edit: Il semble que la réponse Pyth de 5 octets de FryAmTheEggman soit gagnante! N'hésitez pas à soumettre de nouvelles réponses, cependant; si vous pouvez obtenir quelque chose de plus court, je changerai la réponse acceptée.

Cas de test

ndiv(1) -> 1
ndiv(2) -> 2
ndiv(12) -> 6
ndiv(30) -> 8
ndiv(60) -> 12
ndiv(97) -> 2
ndiv(100) -> 9

Classements

Voici un extrait de pile pour générer à la fois un classement régulier et un aperçu des gagnants par langue.

Pour vous assurer que votre réponse apparaît, veuillez commencer votre réponse avec un titre, en utilisant le modèle Markdown suivant:

# Language Name, N bytes

Nest la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores dans le titre, en les barrant. Par exemple:

# Ruby, <s>104</s> <s>101</s> 96 bytes

Si vous souhaitez inclure plusieurs nombres dans votre en-tête (par exemple parce que votre score est la somme de deux fichiers ou si vous souhaitez répertorier les pénalités de drapeau d'interprète séparément), assurez-vous que le score réel est le dernier numéro de l'en-tête:

# Perl, 43 + 2 (-p flag) = 45 bytes

Vous pouvez également faire du nom de la langue un lien qui apparaîtra ensuite dans l'extrait de classement:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes

Réponses:


19

Pyth, 5

l{yPQ

Utilise l'opération de sous-ensembles sur les facteurs premiers de l'entrée, puis conserve uniquement les listes uniques de facteurs et renvoie ce nombre.

Suite de tests

Explication

Utiliser 25 comme exemple, pour que la liste des sous-ensembles ne soit pas très longue

l{yPQ     ## implicit:  Q = eval(input()) so Q == 25
   PQ     ## Prime factors of Q, giving [5, 5]
  y       ## All subsets, giving [[], [5], [5], [5, 5]]
 {        ## Unique-fiy, giving [[], [5], [5, 5]]
l         ## Length, print implicity

Fascinant. Belle approche
Cyoce

14

C ++ C, 43 57 56 46 43 octets

Sur les suggestions de Martin Büttner:

i,c;f(n){for(i=c=n;i;n%i--&&--c);return c;}

1
Attendez, comptons les deux à la place, pour 43:i,c;f(n){for(i=c=n;i;n%i--&&--c);return c;}
Martin Ender

@ MartinBüttner Wow homme wow. Sérieusement! _ / \ _
Sahil Arora

1
Beau! : ~)!
sweerpotato

11

LabVIEW, 4938 octets

Eh bien, ce n'est évidemment pas adapté pour le golf de code, mais peu importe, donc pour mon premier post et le lolz ici. enter image description here


Bienvenue dans Programmation d'énigmes et Code Golf! Comment avez-vous marqué cela, si cela ne vous dérange pas que je demande? Je n'ai trouvé aucun précédent sur Meta.
bkul

je l'ai enregistré et pris la taille de celui
Eumel

Et c'était 4,938 octets? Pas des kilo-octets, par exemple?
bkul

pour plus de précision, j'ai pris le nombre d'octets et non le nombre de ko
Eumel

4
@bkul Je pense que la confusion est due à la ., ce qui, j'en suis sûr, est censé être un millier de séparateurs, pas un séparateur décimal (comme cela est courant dans certaines langues).
Martin Ender

10

Haskell, 28 octets

f n=sum[0^mod n i|i<-[1..n]]

L'astuce consiste ici à tester si un reste 0utilise la fonction d'indicateur 0^.

0^0 = 1
0^_ = 0

Cela fonctionne car toute puissance positive de 0 est 0, tandis que 0 ^ 0 est combinatoire le produit vide de 1.

Comparez cela au filtrage

f n=sum[1|i<-[1..n],mod n i<1]

7

Dyalog APL , 7 6 octets

≢∘∪⊢∨⍳

Il s'agit d'une fonction sans nom qui peut être nommée puis réutilisée pour chaque ¨cas de test ( ) comme suit:

      f ← ≢∘∪⊢∨⍳
      f¨ 1 2 12 30 60 97 100
1 2 6 8 12 2 9

Explication:

 ┌─┴──┐  
 ∪  ┌─┼─┐
 ∘  │ ∨ │
 ̸≡  ⊢   ⍳

Comptez l' unique du GCD de lui - même et de chacun des entiers-jusqu'à .

Merci à ngn d'avoir enregistré un octet.


Ancienne version: +/0=⍳|⊢

Voilà comment cela fonctionne:

  ┌─┴─┐      
  / ┌─┼───┐  
┌─┘ 0 = ┌─┼─┐
+       ⍳ | ⊢

⍳|⊢1-à-argument argument division-reste
0=booléen si 0 est égal au reste de la division
+/Somme du booléen, c'est-à-dire le nombre de uns.


6

Python 2, 37 octets

f=lambda n,i=1:i/n or(n%i<1)+f(n,i+1)

Une fonction récursive. L'entrée facultative idans le diviseur en cours de test. L'expression (n%i<1)teste la divisibilité, avec True(ce qui équivaut 1) pour les diviseurs. Le résultat est ajouté à l'expression récurrente de i+1. Lorsque i==nest atteint, la division de plancher entière est i/névaluée 1et cette valeur est renvoyée comme cas de base, ce qui représente nelle-même un diviseur de n.


38:

lambda n:sum(n%-~i<1for i in range(n))

Une fonction anonyme. Tests possibles diviseurs 1par n. Cela est déplacé de l' utilisation à 0travers , ce qui ajoute . La sommation des bools utilise le fait que Python traite / as / .n-1range(n)-~1TrueFalse10


6

Rétine , 17 octets

(?<=(.+))(?=\1*$)

Entrée en unaire , sortie en décimal.

Essayez-le en ligne.

Lorsqu'elle est invoquée avec une seule expression régulière, Retina compte simplement les correspondances. Le regex lui-même correspond à une position , où le nombre unaire à gauche de celui-ci est un diviseur de l'entrée entière. J'utilise également le fait que les contournements sont atomiques, de sorte que je n'ai pas besoin d'utiliser une ^ancre.

Le premier lookbehinds capture simplement le préfixe entier dans le groupe 1. Cela ne peut jamais échouer, donc après le coup d'œil, nous savons que c'est ce qui est dans le groupe 1 et cela ne changera plus.

Le lookahead vérifie ensuite si nous pouvons atteindre la fin de la chaîne en répétant la chaîne capturée (notre diviseur potentiel) 0 fois ou plus.


6

J, 10 octets

[:*/1+_&q:

Il s'agit d'un verbe monadique sans nom. Il calcule σ 0 (∏p k α k ) comme ∏ (α k + 1) .

Essayez en ligne avec J.js .

Comment ça marche

[:*/1+_&q:    Right argument: y

      _&q:    Compute all exponents of the prime factorization of y.
    1+        Add 1 to each exponent.
[:*/          Reduce by mutiplication.

Je ne pense pas que cela q:soit autorisé car cela résout une partie essentielle du défi. Que diriez-vous de juste[:+/0=]|~1+i.
FUZxxl

Ce serait un double de cette réponse . De plus, les intégrés ne sont pas interdits par défaut, et le défi ne semble pas les mentionner.
Dennis

Les buildins qui font tout / presque tout le travail d'un défi sont généralement interdits mais je peux suivre votre raisonnement q: .
FUZxxl

1
Ils ne sont pas. Je souhaite qu'ils l'étaient, mais ils ne le sont pas.
Dennis

Hrmpf hrmpf qui craint un peu.
FUZxxl

6

Golfscript, 19 18 17 13 octets

Merci à Martin Büttner .

~.,\{\)%!}+,,

Comment ça marche

~               Evaluate the input, n
 .,             Duplicate the input, create array [0..n-1]
   \            Swap array and n
    {    }+     Add n to block == {n block}
     \          Swap n with i in array
      )         Increment i
       %        n mod i
        !       Logical not so that 1 if divisible by n else 0
           ,    Filter array using block for all i divisible by n
            ,   Get length of the filtered array, the answer

Également

De @Peter Taylor , également en 13 octets.

~:X,{)X\%!},,

Comment ça marche

~               Evaluate the input
 :X             Store input in variable X
   ,            Create array [0..X-1]
    {     },    Filter array using the following block
     )          Increment i in array
      X\        Add X to stack, swap with i
        %       X mod i,
         !      Logical not so that 1 if divisible by n else 0
            ,   Get length of the filtered array, the answer

Pour la même durée, vous pourriez aussi avoir~:X,{)X\%!},,
Peter Taylor

4

J, 13 12 11 octets

Mon premier golf à J. Je l'apprends encore.

Enregistré un octet grâce à Dennis.

Enregistré un octet de plus grâce à randomra.

1+/@,0=i.|]

Explication:

1+/@,0=i.|]
       i.        the array 0 .. n-1
         |]      mod n
     0=          replace 0 by 1, and nonzero entries by 0
1   ,            prepend 1 to the array
 +/@             take the sum

3

Arcyóu , 12 octets

Commençons la fête!

(F(x)(_(d/ x

Cela utilise la fonction intégrée d/. Voici une version sans le intégré (27 octets):

(F(x)(](+(f i(_ 1 x)(‰ x i

Explication:

(F(x)              ; Anonymous function with one parameter x
  (]               ; Increment
    (+             ; Sum
      (f i(_ 1 x)  ; For i in range from 1 to x-1 inclusive:
        (‰ x i     ; x divisible by i

3

CJam, 11 octets

ri_,:)f%0e=

Testez-le ici.

Explication

CJam n'a pas de fonction intégrée pour cela, nous faisons donc la division d'essai.

ri  e# Read input and convert to integer N.
_,  e# Duplicate and turn into range [0 1 ... N-1]
:)  e# Increment each element in the range to get [1 2 ... N]
f%  e# Take N modulo each of the list elements.
0e= e# Count the zeroes.

Prime

Voici une solution intéressante à 12 octets (que je soupçonne être la plus courte dans un langage comme J):

ri_)2m*::*e=

Le résultat est égal au nombre de fois napparaît dans une n x ntable de multiplication:

ri  e# Read input and convert to integer N.
_)  e# Duplicate and increment.
2m* e# Take Cartesian product of [0 1 ... N] with itself.
::* e# Compute the product of each pair.
e=  e# Count the occurrences of N.

3

Matlab, 20 octets

Effectuez k mod npour chaque k = 1,...,n, puis effectuez not(qui transforme chaque nonzer à zéro et chaque zéro à 1) et résumez toutes ces valeurs.

@(n)sum(~mod(n,1:n))

Cela aurait été aussi mon approche!
Luis Mendo

Intéressant que ce soit la même longueur que length(divisors(n)).
Accumulation le

@Acccumulation, vous auriez encore besoin d'ajouter un @(n)pour en faire une soumission valide
flawr

3

Julia, 20 octets

n->sum(i->n%i<1,1:n)

Il s'agit d'une fonction anonyme qui fonctionne comme suit: Pour chaque entier de 1 à l'entrée, testez si le module d'entrée de l'entier est zéro. Si c'est le cas, la valeur sera true, sinon false. Nous additionnons les booléens qui sont implicitement convertis en entiers, ce qui donne le nombre de diviseurs.


Une solution beaucoup plus cool (mais aussi beaucoup plus longue), incluse par souci d'exhaustivité, est

n->prod(collect(values(factor(n))).+1)

Ceci obtient la factorisation canonique de n, ie \prod_{i=1}^k p_i^e_i, et calcule la fonction de diviseur comme τ(n) = \prod_{i=1}^k e_i + 1.




2

Rubis, 27 octets

->n{(1..n).count{|i|n%i<1}}

Exemple d'exécution:

2.1.5 :001 > ->n{(1..n).count{|i|n%i<1}}[100]
 => 9 


2

Regex (.NET), 33 octets

^((?=.*$(?<=^\2*(.+?(?>\2?)))).)+

En supposant que l'entrée et la sortie sont en unaire, et la sortie est tirée de la correspondance principale de l'expression régulière.

Décomposition de l'expression régulière:

  • .*$ ets le pointeur à la fin de la chaîne de sorte que nous ayons toute l'entrée x dans une direction.
  • (?<=^\2*(.+?(?>\2?))) correspond de droite à gauche et vérifie le diviseur en bouclant de x à 0.
    • (.+?(?>\2?)) est une "variable" qui commence à 1 dans la première itération et continue à partir du nombre dans l'itération précédente et boucle jusqu'à x.
    • ^\2* vérifie si x est un multiple de "variable".

Il a essentiellement la même idée que ma réponse pour calculer Phi (pas Pi) . Seul le chèque est différent.

Testez l'expression régulière sur RegexStorm .


2

Labyrinthe , 33 octets

?:}
  :{:}%{{
@ }   " )
!{("{;"}}

Essayez-le en ligne.

Cela met en œuvre la division d'essai. J'ajouterai une explication plus tard. Ce n'est probablement pas optimal, mais j'ai du mal à trouver quelque chose de plus court.


2

Perl 6 , 17 octets

{[+] $_ X%%1..$_} # 17

usage:

say {[+] $_ X%%1..$_}(60); # 12␤

my $code = {[+] $_ X%%1..$_};

say $code(97); # 2␤

my &code = $code;
say code 92; # 6

2

Javascript (ES6), 60 57 42 40 39 37 octets

Cela peut probablement être mieux joué au golf.

n=>{for(d=i=n;i;n%i--&&d--);return d}

Edit 1: j'avais raison. Suppression des accolades après la boucle for.

Edit 2: Golfed à 40 octets avec merci à manatwork et Martin Büttner .

Edit 3: Sauvegarde d'un octet en basant la fonction sur la réponse C ci-dessus.

Edit 4: Merci à ן nɟuɐɯɹɐ ן oɯ et Neil , mais je n'arrive pas à faire fonctionner l'eval.

Edit 5: J'ai oublié de supprimer l'eval.

Tester

n = <input type="number" oninput='result.innerHTML=(

n=>{for(d=i=n;i;n%i--&&d--);return d}

)(+this.value)' /><pre id="result"></pre>


2
Abandonnez les bonnes habitudes. Supprimez les varmots clés. Plus de conseils dans Conseils pour jouer au golf en JavaScript et Conseils pour jouer au golf dans ECMAScript 6 .
manatwork

2
Abandonnez également les mauvaises habitudes: lorsque vous avez le choix entre ++iet i++, choisissez la première (cela n'a rien à voir avec le golf). Devrait également n%i<1enregistrer un octet.
Martin Ender

2
Seulement brièvement testé:n=>{for(d=i=0;i<n;)n%++i<1&&d++;return d}
manatwork

1
38: n => eval ('for (d = 0, i = n; i; d + = n% i - <1); d')
Mama Fun Roll

1
@manatwork Pourquoi pas n%++i||++d?
Neil

2

PowerShell, 34 octets

param($x)(1..$x|?{!($x%$_)}).Count

e.g. 

PS C:\temp> .\divisors-of-x.ps1 97
2
  • créer une liste de nombres de 1 à x, les introduire dans le pipeline |
  • filtrez le pipeline sur (x% item == 0), en convertissant implicitement le résultat modulo en booléen puis en l'inversant à l'aide de !sorte que les diviseurs deviennent $ true et soient autorisés à passer; en utilisant l'alias intégré ?pourWhere-Object
  • rassembler ()et .Countcombien d'articles ont traversé le filtre

Très bien piraté!
bkul

2

Gelée , 2 octets (sans compétition (encore))

Æd

Essayez-le en ligne!

Je pense que cela utilise des fonctionnalités implémentées après l'autre réponse Jelly. Commentez si je me trompe (je ne peux pas regarder chaque commit dans la ligne, vous savez :))


2

Taxi, 2143 octets

Go to Post Office:w 1 l 1 r 1 l.Pickup a passenger going to The Babelfishery.Go to The Babelfishery:s 1 l 1 r.Pickup a passenger going to Cyclone.Go to Cyclone:n 1 l 1 l 2 r.Pickup a passenger going to Cyclone.Pickup a passenger going to Sunny Skies Park.Go to Sunny Skies Park:n 1 r.Go to Cyclone:n 1 l.Pickup a passenger going to Firemouth Grill.Pickup a passenger going to Joyless Park.Go to Firemouth Grill:s 1 l 2 l 1 r.Go to Joyless Park:e 1 l 3 r.[i][Check next value n-i]Go to Zoom Zoom:w 1 r 2 l 2 r.Go to Sunny Skies Park:w 2 l.Pickup a passenger going to Cyclone.Go to Cyclone:n 1 l.Pickup a passenger going to Divide and Conquer.Pickup a passenger going to Sunny Skies Park.Go to Joyless Park:n 2 r 2 r 2 l.Pickup a passenger going to Cyclone.Go to Sunny Skies Park:w 1 r 2 l 2 l 1 l.Go to Cyclone:n 1 l.Pickup a passenger going to Joyless Park.Pickup a passenger going to Divide and Conquer.Go to Divide and Conquer:n 2 r 2 r 1 r.Pickup a passenger going to Cyclone.Go to Cyclone:e 1 l 1 l 2 l.Pickup a passenger going to Trunkers.Pickup a passenger going to Equal's Corner.Go to Trunkers:s 1 l.Pickup a passenger going to Equal's Corner.Go to Equal's Corner:w 1 l.Switch to plan "F" if no one is waiting.Pickup a passenger going to Knots Landing.Go to Firemouth Grill:n 3 r 1 l 1 r.Pickup a passenger going to The Underground.Go to The Underground:e 1 l.Pickup a passenger going to Firemouth Grill.Go to Knots Landing:n 2 r.Go to Firemouth Grill:w 1 l 2 r.Go to Joyless Park:e 1 l 3 r.Switch to plan "N".[F][Value not a divisor]Go to Joyless Park:n 3 r 1 r 2 l 4 r.[N]Pickup a passenger going to The Underground.Go to The Underground:w 1 l.Switch to plan "E" if no one is waiting.Pickup a passenger going to Joyless Park.Go to Joyless Park:n 1 r.Switch to plan "i".[E]Go to Sunny Skies Park:n 3 l 2 l 1 l.Pickup a passenger going to What's The Difference.Go to Firemouth Grill:s 1 l 1 l 1 r.Pickup a passenger going to What's The Difference.Go to What's The Difference:w 1 l 1 r 2 r 1 l.Pickup a passenger going to The Babelfishery.Go to The Babelfishery:e 3 r.Pickup a passenger going to Post Office.Go to Post Office:n 1 l 1 r.

Essayez-le en ligne!

Non golfé:

Go to Post Office: west 1st left 1st right 1st left.
Pickup a passenger going to The Babelfishery.
Go to The Babelfishery: south 1st left 1st right.
Pickup a passenger going to Cyclone.
Go to Cyclone: north 1st left 1st left 2nd right.
Pickup a passenger going to Cyclone.
Pickup a passenger going to Sunny Skies Park.
Go to Sunny Skies Park: north 1st right.
Go to Cyclone: north 1st left.
Pickup a passenger going to Firemouth Grill.
Pickup a passenger going to Joyless Park.
Go to Firemouth Grill: south 1st left 2nd left 1st right.
Go to Joyless Park: east 1st left 3rd right.
[i]
[Check next value n-i]
Go to Zoom Zoom: west 1st right 2nd left 2nd right.
Go to Sunny Skies Park: west 2nd left.
Pickup a passenger going to Cyclone.
Go to Cyclone: north 1st left.
Pickup a passenger going to Divide and Conquer.
Pickup a passenger going to Sunny Skies Park.
Go to Joyless Park: north 2nd right 2nd right 2nd left.
Pickup a passenger going to Cyclone.
Go to Sunny Skies Park: west 1st right 2nd left 2nd left 1st left.
Go to Cyclone: north 1st left.
Pickup a passenger going to Joyless Park.
Pickup a passenger going to Divide and Conquer.
Go to Divide and Conquer: north 2nd right 2nd right 1st right.
Pickup a passenger going to Cyclone.
Go to Cyclone: east 1st left 1st left 2nd left.
Pickup a passenger going to Trunkers.
Pickup a passenger going to Equal's Corner.
Go to Trunkers: south 1st left.
Pickup a passenger going to Equal's Corner.
Go to Equal's Corner: west 1st left.
Switch to plan "F" if no one is waiting.
Pickup a passenger going to Knots Landing.
Go to Firemouth Grill: north 3rd right 1st left 1st right.
Pickup a passenger going to The Underground.
Go to The Underground: east 1st left.
Pickup a passenger going to Firemouth Grill.
Go to Knots Landing: north 2nd right.
Go to Firemouth Grill: west 1st left 2nd right.
Go to Joyless Park: east 1st left 3rd right.
Switch to plan "N".
[F]
[Value not a divisor]
Go to Joyless Park: north 3rd right 1st right 2nd left 4th right.
[N]
Pickup a passenger going to The Underground.
Go to The Underground: west 1st left.
Switch to plan "E" if no one is waiting.
Pickup a passenger going to Joyless Park.
Go to Joyless Park: north 1st right.
Switch to plan "i".
[E]
Go to Sunny Skies Park: north 3rd left 2nd left 1st left.
Pickup a passenger going to What's The Difference.
Go to Firemouth Grill: south 1st left 1st left 1st right.
Pickup a passenger going to What's The Difference.
Go to What's The Difference: west 1st left 1st right 2nd right 1st left.
Pickup a passenger going to The Babelfishery.
Go to The Babelfishery: east 3rd right.
Pickup a passenger going to Post Office.
Go to Post Office: north 1st left 1st right.

Explication:

Convert stdin to a number and store it in three locations for three purposes:
   Original (Sunny Skies Park)
   Counter for tested values (Joyless Park)
   Counter for divisors found (Firemouth Grill)
Divide the original by each Joyless Park value in turn.
If the division result equals the truncated division result, then it's a divisor.
When a divisor is found, subtract one from Firemouth Grill.
Repeat until Joyless Park hits zero.
Pickup the original from Sunny Skies Park and subtract the value from Firemouth Grill.
Convert the result to a string and print to stdout.


2

Formule Excel, 42 28 octets

Edit: je viens de réaliser que je n'ai pas besoin d'utiliser INDIRECT , économisant 14 octets!

Les éléments suivants doivent être saisis sous forme de formule matricielle ( Ctrl+ Shift+ Enter):

=SUM(--NOT(MOD(N,ROW(1:N))))

Où N est le nombre à tester.

Exemples:

{SUM(--NOT(MOD(32,ROW(1:32))))}
Result: 6
{SUM(--NOT(MOD(144,ROW(1:144))))}
Result: 15

Explication:

SUM(--NOT(MOD(N,ROW(1:N))))       Full formula

                ROW(1:N)          Generates an array of row numbers e.g {1;2;3;4;...N}
          MOD(N,ROW(1:N))         Does N MOD {1;2;3;4;,...N}
      NOT(MOD(N,ROW(1:N)))        Coerces zeros to ones, so that they may be counted, but actually returns an array of TRUE;FALSE;FALSE;...
    --NOT(MOD(N,ROW(1:N)))        Coerces the TRUEs to 1s and FALSEs to 0s.
SUM(--NOT(MOD(N,ROW(1:N))))       Sum the ones for the result.


1

Mathematica, 16 octets

Length@*Divisors

Composition simple des fonctions intégrées.


1

Minkolang 0,13 , 16 octets

ndd[0ci1+%,-]-N.

Vérifiez tous les cas ici.

Explication

ndd           Takes number from input and duplicates it twice (n)
[             Opens for loop that runs n times
 0c           Copies bottom of stack to top (n)
   i1+        Loop counter + 1 (d)
      %       Modulo - pops d,n, then pushes n%d
       ,      Not - 1 if equal to 0, 0 otherwise
        -     Subtract
         ]    Close for loop
-             Subtract (n - 1 for each non-divisor)
N.            Output as number and stop.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.