Hübsche Druckpolynome


38

Einführung

Menschen sind eine bemerkenswerte Spezies, aber manchmal ist es sehr umständlich, sie zu verstehen - besonders für Computer. Insbesondere scheinen wir es zu mögen, Polynome auf sehr verschlungene Weise mit scheinbar willkürlichen Regeln zu schreiben.

Was ist das kürzeste Programm, das Sie schreiben können, um ein Polynom nach diesen Regeln korrekt zu formatieren?

Herausforderung

Eingang

Eine Liste von ganzen Zahlen zwischen -1000 und 1000 (einschließlich), die die Koeffizienten eines Polynoms darstellen, wobei der letzte Eintrag der Koeffizient von x ^ 0 (die Konstante) ist, der vorletzte der Koeffizient von x ^ 1 usw.

Ausgabe

Ein String, der dieses Polynom in der korrekt formatierten mathematischen Notation des Menschen darstellt.

Regeln:

  • Das Vorzeichen des Leitkoeffizienten wird nur angezeigt, wenn es negativ ist.

Right: -x^2+3

Wrong: +x^2+3

  • Komponenten mit dem Koeffizienten 0 werden nicht gedruckt (mit Ausnahme des Eckfalles, bei dem alle Koeffizienten 0 * sind).

Right: x^5-x^2+3

Wrong: x^5+0x^4+0x^3-x^2+0x+3

  • Koeffizienten -1und +1sollen ohne die 1 angezeigt werden, es sei denn, sie sind die Konstante.

Right: x^5-x^2+1

Wrong: 1x^5-1x^2+1

  • Der Exponent wird nur angezeigt, wenn er größer als 1 ist, und die Variable wird nur angezeigt, wenn der Exponent größer als 0 ist.

Right: 3x^3-7x^2+2x+1

Wrong: 3x^3-7x^2+2x^1+1x^0

  • * Eckfall: Während Nullwerte normalerweise dazu führen, dass diese Komponente nicht gedruckt wird, sollte die Konstante 0 gedruckt werden, wenn alle Koeffizienten Null sind.

Right: 0

Wrong: 0x+0

Wrong: (nothing)

  • Dies ist Code-Golf, also wird der Gewinner das Programm mit den wenigsten Bytes sein.

Beispiel für Ein- und Ausgabe

Input:                  Output:
      [0]                      0
      [0,0]                    0
      [0,-1,35,0]             -x^2+35x
      [5,1,7,-9]               5x^3+x^2+7x-9
      [100,0,0,-1]             100x^3-1
      [931,21,-11,1]           931x^3+21x^2-11x+1

Ich freue mich auf Ihre Lösungen. Habe Spaß!

BEARBEITEN:

  • Sie können Operationen mit Leerzeichen umgeben, wenn Sie dies wünschen. Also 3x+5und 3x + 5beiden geht es gut. 3x+ 5und 3x +5sind es nicht.
  • Wenn Sie tatsächliche Exponentenzeichen (z. B. in Tex) erzeugen möchten, ist dies zulässig, da dies noch näher an der Schreibweise der Menschen liegt.
  • Koeffizienten müssen ohne Dezimalstellen angegeben werden, z. B. 9x^2ist richtig, 9.0x^2nicht.

7
Eine Frage, die ich im Sandkasten hätte stellen sollen, aber nicht, können wir mit Leerzeichen zwischen den Operatoren drucken? Also 3x^2 + 4gegen 3x^2+4?
Giuseppe

1
Müssen wir Exponenten mit Carets ausgeben? Oder wäre das Erzeugen eines tatsächlichen hochgestellten Zeichens erlaubt (zB für eine Antwort in TeX)?
Tutleman

3
@ KevinCruijssen Ich bin nicht der OP, aber ich würde nicht sagen, weil die meisten Menschen nicht so schreiben.
ShreevatsaR

2
@ManishKundu Ja sicher, Sie können die Eingabe als Zeichenfolgen verwenden.
Oisín Moran

1
@ OisínMoran Nichts flippig, nur um sicher eine einfache Herstellung 1x-> xErsatz ändert sich nicht 21x^2in 2x^2.
DLosc

Antworten:


10

Retina 0,8,2 , 56 Bytes

(?=( \S+)+)
x^$#1
\b0x.\d+ 

\b1x
x
x.1 
x 
 0

 -
-
 
+

Probieren Sie es online! Link enthält Testfälle. Erläuterung:

(?=( \S+)+)
x^$#1

Fügen Sie alle Befugnisse von ein x, einschließlich, x^1aber nicht x^0.

\b0x.\d+ 

Löschen Sie alle Potenzen von xmit Null-Koeffizienten, aber 0(noch) nicht mit einem Trailing .

\b1x
x

Löschen Sie einen Multiplikator von 1(aber keine Konstante 1).

x.1 
x 

Löschen Sie die ^1von x^1.

 0

Löschen Sie eine Konstante 0, es sei denn, es ist das einzige, was noch übrig ist.

 -
-

Löschen Sie das Leerzeichen vor a -.

 
+

Ändern Sie alle verbleibenden Leerzeichen in +s.


6

JavaScript (ES6), 107 106 Bytes

a=>a.map(c=>c?s+=(c>0&&s?'+':_)+(!--e|c*c-1?c:c<0?'-':_)+(e?e-1?'x^'+e:'x':_):e--,e=a.length,_=s='')&&s||0

Probieren Sie es online!

Wie?

Die Ausgabe wird erstellt, indem die folgenden Formeln auf jeden Koeffizienten c des Eingabearrays a [] angewendet werden, während der aktuelle Exponent e verfolgt wird .

1. Formel: Pluszeichen

Wenn der Koeffizient streng positiv ist und dies nicht der erste Term im Ausgabeausdruck ist, fügen wir a hinzu +. Ansonsten hängen wir nichts an.

c > 0 && s ? '+' : _

2. Formel: Minuszeichen und Koeffizient

Wenn der Exponent Null ist oder der absolute Wert des Koeffizienten ungleich 1 ist, fügen wir den Koeffizienten hinzu (der eine führende Zahl enthalten kann) - ). Ansonsten hängen wir entweder a -(wenn der Koeffizient negativ ist) oder nichts an.

!--e | c * c - 1 ? c : c < 0 ? '-' : _

3. Formel: Variable und Exponent

Wenn der Exponent 0 ist, wird nichts angehängt. Wenn der Exponent 1 ist, hängen wir an x. Andernfalls wird x^gefolgt vom Exponenten angehängt.

e ? e - 1 ? 'x^' + e : 'x' : _

Dies schlägt in diesem Fall fehl: [0,1,35,0], es wird mit + x ^ 2
Makotosan

2
@Makotosan Vielen Dank für den Hinweis! Sollte jetzt OK sein.
Arnauld

5

Stax , 37 Bytes

┴₧↕ê♦•Vªâÿσ9s╘dσ■à@@ⁿ■o─╦ñºº┌x╡ER▓ δ¿

Führen Sie es online aus und debuggen Sie es

Hier ist die ausgepackte, ungolfierte Version.

r{          reverse the input and map using block ...
  |c        skip this coefficient if it's falsy (zero)
  0<.+-@    sign char; e.g. '+'
  _|aYv i!+ abs(coeff)!=1 || i>0
    y$      str(abs(coeff)); e.g. '7'
    z       ""
  ?+        if-then-else, concatenate; e.g. '+7'
  "x^`i"    string template e.g. 'x^3' or 'x^0'
  iJ(T+     truncate string at i*i and trim. e.g. 'x^3' or ''
mr$         re-reverse mapped array, and flatten to string
c43=t       if it starts with '+', drop the first character
c0?         if the result is blank, use 0 instead

Führen Sie dieses aus


5

Python 3, 279 277 258 251 Bytes

k=str.replace
def f(x):
 z=len(x)
 y='--'*(['-1']==[c for c in x if'0'!=c][:1])
 for i,v in enumerate(x):
  p=str(z+~i)
  if v in'-1'and~i+z:y+='+x^'+p
  elif'0'!=v:y+='+'+v+'x^'+p
 return y and k(k(k(k(y[1:],'+-','-'),'^1',''),'x^0',''),'-+','-')or 0

Übernimmt die Eingabe als Liste von Zeichenfolgen. Diese Lösung ist noch nicht sehr erfolgreich. Dies funktioniert im Wesentlichen, indem Dinge ersetzt werden, die dem Ausgabeformat entsprechen, wodurch die Byteanzahl stark erhöht wird.

Probieren Sie es online!

Besonderer Dank geht an ovs und NK1406 .


Alle Fehler behoben.
Manish Kundu

Sie können Ihre Gleichheitsprüfungen neu anordnen, um sie if'0'!=iund zu erstellen if'-1'==i.
Zacharý


@ovs vielen Dank
Manish Kundu



4

APL (Dyalog Classic) , 114 113 109 107 106 Bytes

{{⍵≡'':⍕0⋄⍵↓⍨'+'=⊃⍵}∊⍵{{'1x'≡2↑1↓⍵:¯1⌽1↓1⌽⍵⋄⍵}('-0+'[1+×⍺]~⍕0),∊(U/⍕|⍺),(U←⍺≠0)/(⍵>⍳2)/¨'x'('^',⍕⍵)}¨⌽⍳⍴⍵}

Probieren Sie es online!

-4 Bytes danke an @dzaima!

Dies kann definitiv weiter abgespielt werden. Dafür braucht man⎕IO←0


Ich habe diese zwei Bytes endlich rasiert ...
Zacharý

3

Pip , 78 Bytes

(RV(B."x^"._MERVg)J'+)R[`\b0[^+]+``x.0|\^1|^\++|\++$``\b1x``\++-?`][xx'x_@v]|0

Nimmt die Koeffizienten als Befehlszeilenargumente. Probieren Sie es online!

Verwendet ME(map-enumerate) und J(join), um etwas vom Formular zu generieren 0x^3+-1x^2+35x^1+0x^0, und dann eine Reihe von Regex-Ersetzungen, um dies in das richtige Format umzuwandeln.



3

Python 3, 161 162 Bytes

Ein Fehler wurde behoben, der Ovs zu verdanken war.

l=len
lambda p:''.join(['+'*(i>0)*(c>0)+(str(c)[:-1],str(c))[abs(c)!=1or i==l(p)-1]+'x'*(i!=l(p)-1)+('^%d'%(l(p)+~i))*(i<l(p)-2)for i,c in enumerate(p)if c])or'0'

Erweitert:

l=len # Alias the len function since we use it a lot
lambda p: ''.join([ # Join a list of strings
    '+'*(i>0)*(c>0) # Prepend a + if this isn't the first term and the coefficient is positive
    + (str(c)[:-1], str(c))[abs(c) != 1 or i == l(p) - 1] # If the coefficient is 1 and this isn't the last term, delete the '1' from the string representation, otherwise just use the string representation
    + 'x' * (i != l(p) - 1) # If this isn't the last term, append an x
    + ('^%d' % (l(p) + ~i)) * (i < l(p) - 2) # If this isn't one of the last two terms, append the exponent
for i, c in enumerate(p) if c]) # Iterating over each coefficient with its index, discarding the term if the coefficient is zero
or '0' # If all of the above resulted in an empty string, replace it with '0'

3

C # , 237 Bytes

c=>{var b=1>0;var r="";int l=c.Length;var p=!b;for(int i=0;i<l;i++){int n=c[i];int e=l-1-i;var o=p&&i>0&&n>0?"+":n==-1&&e!=0?"-":"";p=n!=0?b:p;r+=n==0?"":o+(e==0?$"{n}":e==1?$"{n}x":n==1||n==-1?$"x^{e}":$"{n}x^{e}");}return r==""?"0":r;}

1
Willkommen bei PPCG!
Martin Ender

3

Sauber , 172 Bytes

import StdEnv,Text
r=reverse
@""="0"
@a|a.[size a-1]<'0'=a+"1"=a
? -1="-"
?1=""
?a=a<+""
$l=join"-"(split"+-"(join"+"(r[?v+e\\v<-r l&e<-["","x":map((<+)"x^")[1..]]|v<>0])))

Probieren Sie es online!


@BMO vorübergehend behoben, bis mehr Golf gespielt wird.
Οurous

3

Wolfram Language / Mathematica, 39 Bytes

TraditionalForm@Expand@FromDigits[#,x]&

Probieren Sie es online!

Es hat sich herausgestellt, dass ein eingebautes Gerät in der richtigen Reihenfolge eingebaut ist.

Vorherige Lösung:

Wolfram Language / Mathematica, 93 Bytes

StringReplace[StringRiffle[ToString/@InputForm/@MonomialList@FromDigits[#,x],"+"],"+-"->"-"]&

Zumindest für mich ist dies überraschend lang für eine Sprache, die für mathematische Manipulationen entwickelt wurde. Es scheint, als Expand@FromDigits[#,x]&sollte es funktionieren, aber die Standardreihenfolge für Polynome ist die Umkehrung der in der Frage geforderten Reihenfolge. Daher ist etwas zusätzliches Finagling erforderlich.

Erläuterung

FromDigits[#,x]               converts input list to polynomial (technically converts to a number in base x)
MonomialList@                 gets list of terms of polynomial
InputForm/@                   converts each term to the form a*x^n
ToString/@                    then to a string version of that
StringRiffle[...,"+"]         joins using +'s
StringReplace[...,"+-"->"-"]& replaces +-'s with -'s

Sollte nicht SringReplacesein StringReplace?
Scott Milner

@ ScottMilner Muss ein Fehler gewesen sein, als ich es kopiert habe. Danke, dass du es bemerkt hast!
DanTheMan

3

Python3: 150 bis 146 Bytes

f=lambda l:''.join('+-'[a<0]+str(a)[a<0:5*((abs(a)!=1)|(1>i))]+'x^'[:i]+str(i)[:i-1]for i,a in zip(range(len(l)-1,-1,-1),l)if a).lstrip('+')or '0'

(frühere Implementierungen):

f=lambda l: ''.join('+-'[a<0]+str(a)[a<0:5*((abs(a)!=1)|(1>i))]+'x^'[:i]+str(i)[:i-1] for i,a in zip(range(len(l)-1,-1,-1),l) if a).lstrip('+') or '0'

Sie können es online ausprobieren

Ein großes Lob an: @Benjamin


1
Arhg, hab mich! Sie verringern es um 4, indem Sie einige Leerzeichen entfernen:f=lambda l:''.join('+-'[a<0]+str(a)[a<0:5*((abs(a)!=1)|(1>i))]+'x^'[:i]+str(i)[:i-1]for i,a in zip(range(len(l)-1,-1,-1),l)if a).lstrip('+')or '0'
Benjamin

3

Perl 5 -a , 94 Bytes

($_=shift@F)&&push@a,@a*!/-/>0&&'+',@F?s/\b1\b//r:$_,@F>0&&'x',@F>1&&'^'.@F while@F;say@a?@a:0

Probieren Sie es online!


Scheint nicht richtig zu funktionieren, wenn der endgültige (konstante) Koeffizient 1 oder -1 ist.
Nwellnhof

Dang. Muss das kaputt gemacht haben, als ich Golf gespielt habe. Behebung mit ein paar Bytes mehr.
Xcali


2

Haskell , 166 163 Bytes

g s|l<-length s,v:w:r<-id=<<["- +"!!(1+signum m):(id=<<[show$abs m|abs m>1||e==0]++["x"|e>0]++['^':show e|e>1])|(e,m)<-zip[l-1,l-2..]s,m/=0]=[v|v>'+']++w:r|1<3="0"

Probieren Sie es online! Anwendungsbeispiel: g [0,-1,35,0]Erträge "-x^2+35x".


Vorherige 166-Byte-Lösung, die etwas besser lesbar ist:

0#n=show n
m#n=id=<<[show n|n>1]++"x":['^':show m|m>1]
m%0=""
m%n|n<0='-':m#(-n)|1<3='+':m#n
g s|l<-length s,v:m:r<-id=<<zipWith(%)[l-1,l-2..]s=[v|v>'+']++m:r|1<3="0"

Probieren Sie es online!


2

Ruby , 111 Bytes

->a{i=a.size;s=a.map{|x|i-=1;"%+d"%x+[?x,"x^#{i}",""][i<=>1]if x!=0}*'';s[0]?s.gsub(/(?<!\d)1(?=x)|^\+/,""):?0}

Probieren Sie es online!

Das in Ruby zu lösen, stellte sich als etwas frustrierend heraus, hauptsächlich aufgrund der Tatsache, dass im Gegensatz zu den meisten Sprachen in Ruby (fast) alles wahr ist, einschließlich Nullen und leerer Zeichenketten, so dass selbst eine einfache Überprüfung auf Null nicht annähernd möglich ist so kurz wie x? .

Ich spielte mit verschiedenen Methoden, um die Saite zu konstruieren, und entschied mich schließlich für eine Mischung aus mehreren Ansätzen:

  • Terme mit 0 Koeffizienten werden mit einer einfachen Bedingung gelöscht
  • + und - Zeichen werden durch Formatieren der Syntax mit erzwungenen Zeichen erzeugt:%+d
  • Die richtige Form oder x^i wird mit Hilfe der Raketenoperator-Indizierung ausgewählt[...][i<=>1]
  • Führende + und unnötige 1-s werden durch Regex-Ersetzungen entfernt

2

Schale , 44 43 41 40 Bytes

|s0Ψf¤|□ṁ`:'+f¹zμ+↓s²_&ε²¹↑□¹+"x^"s)¹m←ṡ

Probieren Sie es online!

Das fühlt sich ein bisschen klobig an; Husk ist nicht für die Manipulation von Saiten optimiert. Ich habe einige Ideen aus der Stax-Antwort entlehnt .

Erläuterung

         Implicit input, say L = [2,-3,0,-1].
         First we compute the exponents.
ṡ        Reversed indices: [4,3,2,1]
m←       Decrement each: [3,2,1,0]
         Then we format the individual terms of the polynomial.
zμ...)¹  Zip with L using two-argument lambda:
          Arguments are coefficient and index, say C = -3 and I = 2.
+"x^"s    Convert I to string and concatenate to "x^": "x^2"
↑□¹       Take first I*I characters (relevant when I = 0 or I = 1): "x^2"
_&ε²¹     Check if abs(C) <= 1 and I != 0, negate; returns -1 if true, 0 if false.
↓s²       Convert C to string and drop that many elements (from the end, since negative).
          Result: "-3"
          The drop is relevant if C = 1 or C = -1.
+         Concatenate: "-3x^2"
         Result of zipping is ["2x^3","-3x^2","x","-1"]
f¹       Keep those where the corresponding element of L is nonzero: ["2x^3","-3x^2","-1"]
         Next we join the terms with + and remove extraneous +s.
ṁ        Map and concatenate
`:'+      appending '+': "2x^3+-3x^2+-1+"
Ψf       Adjacent filter: keep those chars A with right neighbor B
¤|□       where at least one of A or B is alphanumeric: "2x^3-3x^2-1"
|s0      Finally, if the result is empty, return "0" instead.

2

Perl 6 , 97 Bytes

{$!=+$_;.map({('+'x?($_&&$++&$_>0)~.substr(--$!&&2>.abs)~(<<''x>>[$!]//'x^'~$!))x?$_}).join||'0'}

Probieren Sie es online!

Erläuterung:

$!=+$_;

$! Verfolgt den aktuellen Exponenten.

'+'x?($_&&$++&$_>0)

Addiere +vor positiven Koeffizienten, außer wenn es der erste ist, der nicht Null ist. Der $_&&Kurzschluss stellt sicher, dass die anonyme Zustandsvariable $nur für Nicht-Null-Koeffizienten inkrementiert wird. Die &Kreuzung wird reduziert, wenn sie mit Bool zusammengedrückt wird ?.

.substr(--$!&&2>.abs)

Dekrement $!. Zerhacken Sie den Koeffizienten 1 oder -1, sofern er nicht konstant ist.

<<''x>>[$!]//'x^'~$!

Sonderfall lineare und konstante Terme. Die Verwendung des Anführungszeichen-Schutzkonstrukts << >> ist ein Byte kürzer als das entsprechende ('','x')oder 2>$!??'x'x$!!!'x^'~$!.

x?$_

Blenden Sie keine Terme aus, aber werten Sie den vorhergehenden Ausdruck immer auf die --$!Nebenwirkung aus.

||'0'

Rückgabe, 0wenn alle Koeffizienten Null sind.


2

Java 8, 202 176 174 173 Bytes

a->{String r="";int j=a.length;for(int i:a)r+=i==0*j--?"":"+"+i+(j<1?"":j<2?"x":"x^"+j);return r.isEmpty()?"0":r.substring(1).replace("+-","-").replaceAll("(\\D)1x","$1x");}
  • 26 Bytes dank @Nevay .

Erläuterung:

Probieren Sie es online aus.

a->{                     // Method with String-array parameter and String return-type
  String r="";           //  Result-String, starting empty
  int j=a.length;        //  Power-integer, starting at the size of the input-array
  for(int i:a)           //  Loop over the array
    r+=i==0              //   If the current item is 0
           *j--?         //   (And decrease `j` by 1 at the same time)
        ""               //    Append the result with nothing
       :                 //   Else:
        "+"              //    Append the result with a "+",
        +i               //    and the current item,
        +(j<1?           //    +If `j` is 0:
           ""            //      Append nothing more
          :j<2?          //     Else-if `j` is 1:
           "x"           //      Append "x"
          :              //     Else:
           "x^"+j);      //      Append "x^" and `j`
  return r.isEmpty()?    //  If `r` is still empty
    "0"                  //   Return "0"
   :                     //  Else:
    r.substring(1)       //   Return the result minus the leading "+",
     .replace("+-","-")  //   and change all occurrences of "+-" to "-",
     .replaceAll("(\\D)1x","$1x");}
                         //   and all occurrences of "1x" to "x"

1
176 Bytes:a->{String r="";int j=a.length;for(int u:a)r+=u==(j^j--)?"":"+"+u+(j<1?"":j<2?"x":"x^"+j);return r.isEmpty()?"0":r.substring(1).replace("+-","-").replaceAll("([+-])1x","$1x");}
Nevay

1
@Nevay Mir ist erst jetzt klar, dass alle Eingaben Ganzzahlen sind. Ich habe eine Zeichenfolgeeingabe verwendet, da ich dachte, dass auch Dezimaleingaben zulässig sind.>.> Trotzdem danke für die -26 Bytes. Und ich konnte 2 weitere Golf spielen, indem ich (j^j--)zu wechselte 0*j--.
Kevin Cruijssen

2

Python, 165 Bytes

lambda a:"".join([("+"if c>0 and i+1<len(a)else"")+(str(c)if i==0 or abs(c)!=1 else "")+{0:"",1:"x"}.get(i,"x^"+str(i))for i,c in enumerate(a[::-1])if c][::-1])or"0"

1

PHP, 213 Bytes

$p=0;for($i=count($a=array_reverse(explode(',',trim($argv[1],'[]'))))-1;$i>=0;$i--)if(($b=(float)$a[$i])||(!$i&&!$p)){$k=abs($b);echo ($b<0?'-':($p?'+':'')).((($k!=1)||!$i)?$k:'').($i>1?'x^'.$i:($i?'x':''));$p=1;}

Befehlszeilenargument wie von OP angefordert (einzelnes Argument mit Klammern und Kommas).

Schöner Druck und eine Erklärung:

$p = false; /* No part of the polynomial has yet been printed. */
for ($i = count($a = array_reverse(explode(',',trim($argv[1],'[]')))) - 1; $i >= 0; $i--)
{
    $b = (float)$a[$i]; /* Cast to float to avoid -0 and numbers like 1.0 */
    if (($b != 0) or (($i == 0) and !$p)) /* Print, if $b != 0 or the constant if there is no part until here. */
    {
        $k = abs($b);
        echo ($b < 0 ? '-' : ( $p ? '+' : '')); /* Sign. The first sign is suppressed (if $p is false) if $b positive. */
        echo ((($k != 1) || ($i == 0)) ? $k : '');  /* Coefficient */
        echo ($i > 1 ? 'x^' . $i : (($i != 0) ? 'x' : ''));  /* x^3, x^2, x, constant with empty string. */
        $p = true; /* Part of the polynomial has been printed. */
    }
}

1

PowerShell, 295 Byte

$c=$args[0]
$p=$c.length-1
$i=0
$q=""
while($p -ge 0){$t="";$e="";$d=$c[$i];switch($p){0{$t=""}1{$t="x"}Default{$t="x^";$e=$p}}if($d-eq 0){$t=""}elseif($d-eq 1){$t="+$t$e"}elseif($d-eq-1){$t="-$t$e"}elseif($d-lt 0 -or$i -eq 0){$t="$d$t$e"}else{$t="+$d$t$e"}$q+=$t;$i++;$p--}if($q -eq""){$q=0}
$q
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.