Eşsiz ikizleri bulun


28

Size A ve B negatif olmayan tam sayıların iki Dizisi / Listesi / Vektörü verilecektir . Göreviniz çıkışına tam sayı en yüksek olduğu N hem de görünür olduğu A ve B , ve ayrıca hem tektir A ve B .


Test Durumları:

A, B -> Çıktı

[6], [1, 6] -> 6
[1, 2, 3, 4], [4, 5, 6, 7] -> 4
[0, 73, 38, 29], [38, 29, 73, 0] -> 73
[1, 3, 4, 6, 6, 9], [8, 7, 6, 3, 4, 3] -> 4
[2, 2, 2, 6, 3, 5, 8, 2], [8, 7, 5, 8] -> 5
[12, 19, 18, 289, 19, 17], [12, 19, 18, 17, 17, 289] -> 289
[17, 29, 39, 29, 29, 39, 18], [19, 19, 18, 20, 17, 18] -> 17
[17, 29, 39, 29, 29, 39, 18, 18], [19, 19, 18, 20, 17, 18] -> 17

Yanıtlar:


7

Jöle , 7 bayt

fċ@ÐṂ;Ṁ

Çevrimiçi deneyin!

Nasıl çalışır

fċ@ÐṂ;Ṁ  Main link. Left argument: A. Right argument: B

f        Filter; keep those elements of A that appear in B.
   ÐṂ    Yield all elements of the result for which the link to left yields a
         minimal value (2).
 ċ@        Count the occurrences of the element...
     ;     in the concatenation of A and B.
      Ṁ  Take the maximum.

7

Bash + coreutils, 49 bayt

U()(sort -rn|uniq -u$1)
(U<<<$1;U<<<$2)|U D|sed q

1 byte kapalı golf oynamak için @ seshoumara için teşekkürler!

Çevrimiçi deneyin!

Nasıl çalışır

uniq sıralı girdi alır ve komut satırı bayraklarına bağlı olarak bir veya birkaç eylem gerçekleştirir.

U<<<$1ve U<<<$2fonksiyonu Ubirinci ve ikinci komut satırı argümanıyla giriş olarak çağırın . Her biri için, sort -rn|uniq -ugirişi benzersiz olarak ( ) ve yalnızca benzersiz satırları ( ) basacak olan uniq için -nazalan düzende ( -r) sıralayarak yürütülür .-u

Her ikisinin de çıkışı (her bir dizinin benzersiz öğeleri) bir araya getirilir ve birleştirilir U D, yani
sort -rn|uniq -uD. Bu sefer, uniq sadece kopya satırları ( -D) ve her birinin sadece ilk tekrarını basacaktır .

Kılavuz sayfası tüm tekrarları basacağını söylese de, eklenenler sadece kopyalanmış satırların ilk oluşumunu basmaya -uneden olur -D. Bu davranış normalde ile elde edilir uniq -d.

Son olarak, sed qderhal çıkar ve girdisini (her iki dizinin benzersiz öğeleri) ilk satırına indirir. Çıkış azalan düzende sıralandığından, bu maksimumdur.


6

Pyth, 12 9 bayt

Dene

eS@Fm.m/d

Bay Xcoder sayesinde 3 bayt kurtarıldı.

açıklama

eS@Fm.m/d
    m  /d   Count the occurrences of each element.
     .m     Take only those that appear the minimum number of times.
  @F        Apply the above to A and B and take the intersection.
eS          Take the largest.

Güzel! Benim çözümüm de 12 bayttı .
Bay Xcoder

Çözümümü biraz aşağıya atmak , 9 byte (kullanmak eS@Fm.m/d) ve iki listenin girişi olarak giriş yapmak.
Bay Xcoder

@ Mr.Xcoder Kendi cevabı olacak kadar farklı görünüyor.

Zorluğun OP'si olduğum için, göndermeyi istemiyorum. Mevcut yaklaşımınızı bir alternatif olarak söyleyerek sadece kullanabilirsiniz ve kredi verin (elbette isterseniz)
Bay Xcoder


5

05AB1E , 9 8 bayt

-1 The Outgolfer sayesinde bayt

εТÏ}`Ãà

Çevrimiçi deneyin!

ε   }    # For each input
 Ð¢Ï     #   Get the unique elements
     `Ã  # Keep only the elements that appear in both lists
       à # Keep the greatest element
         # Implicit print

5

Kabuğu , 7 bayt

→►≠OfEΠ

İki listenin bir listesi olarak girdi alır, herhangi bir sayıda liste için de çalışır (mümkünse her birinde tam olarak bir kez oluşan en yüksek sayıyı döndürerek). Çevrimiçi deneyin!

açıklama

Bu, (ab) yeni "maksimum by" işlevini kullanan ilk Husk cevabıdır .

→►≠OfEΠ  Implicit input, say [[3,2,1,3],[1,2,3,4]]
      Π  Cartesian product: [[3,1],[2,1],[3,2],[2,2],[1,1],[3,3],[1,2],[3,1],[3,4],[2,3],[1,3],[3,2],[2,4],[3,3],[1,4],[3,4]]
    fE   Keep those that have equal elements: [[2,2],[1,1],[3,3],[3,3]]
   O     Sort: [[1,1],[2,2],[3,3],[3,3]]
 ►≠      Find rightmost element that maximizes number of other elements that are not equal to it: [2,2]
→        Take last element: 2

4

Bash + coreutils, 60 bayt

f()(sort -rn<<<"$1"|uniq -u);grep -m1 -wf<(f "$1") <(f "$2")

Çevrimiçi Deneyin

Bash, 89 bayt

c()(for e;{((e^$1||r++,2^r));});for x in $1 $2;{((x<r))||c $x $1||c $x $2||r=$x;};echo $r

TIO


1
Kullanım sort -rnile sed qsonunda yerine tail -1tıraş 1 byte. grep -wfBtw ile büyük bulmak . +1
seshoumara

@seshoumara, bahşiş için teşekkür ederim, aslında -m1 grep seçeneği ile 3 byte'ı tıraş edebilirim.
Nahuel Fouilleul


3

J, 23 bayt

>./@([-.-.)&(-.-.@~:#])

(-.-.@~:#]) tekrarlanan öğeleri listeden siler

& bunu iki tarafa da yap

([-.-.) A'nın B kesişmesini istiyoruz. Bu, eşdeğer ifadedir: "A eksi (A eksi B)".

>./ Max al

Çevrimiçi deneyin!


Eşdeğer olarak, kesişme kısmını ile değiştirebilirsiniz e.~#]. Golf /.oynamak zor oldu ... Başarısız olmak ((1=#)/.~#~.)için -key'i kullanmaya çalıştım ( ilk bölüm için sayım 2 byte daha uzun)
cole

@ cole, evet, ben de bir anahtar yaklaşım denedim, ve aynı zamanda kendini sınıflandırmak. Yine de gönderimimi başka bir yaklaşımla yenemedim.
Jonah

2

PowerShell , 94 bayt

param($a,$b)filter f($x){$x|group|?{$_.count-eq1}}
(f($a|sort|?{$_-in((f $b).Name)}))[-1].Name

Çevrimiçi deneyin!

Girdiyi $ave $bdizileri alır. Bir oluşturur filterbu grouparada giriş dizi elemanları s ve sadece olan çeker count -eqiçin UAL1 (yani, yalnızca giriş dizide benzersiz olanlar).

Bir sonraki satır daha sonra algoritmayı oluşturur. Önce biz sort $a, sonra -inda eşsiz öğeleri olanları çıkarırız $b. O zamanlar kendileri eşsizdirlerse, en büyüğü [-1]seçilir ve biz onları alırız .Name. Bu, boru hattında bırakılan ve çıktının kapalı olduğu.


2

Javascript (ES6), 102 86 75 71 bayt

a=>b=>Math.max(...a.map(e=>(g=x=>x.map(y=>y-e||x--,x=1)|!x)(a)*g(b)*e))

102'den 86'ya ulaştığınız için teşekkürler Justinustinariner

86'dan 75’e ulaştığınız için teşekkür ederiz

75 - 71

Çevrimiçi deneyin!


PPCG'ye Hoşgeldiniz! Söyleyebileceğim kadarıyla eve sadece ave içinde bir kez ortaya çıkmamasını sağlamıyor b.
Martin Ender

@MartinEnder Teşekkürler! Cevapsız özledim ayrıntıları yansıtacak şekilde düzenlenmiş!
Nate

1
lastIndexOfBöyle kullanmayı hiç düşünmedim , bu çok zekice. Bunu 86 bayta indirebilirsin: Çevrimiçi deneyin! . Daha fazla bilgi için JS ipuçlarına göz atın .
Justin Mariner

1
Kullanmanın (g=x=>x.filter(y=>y==e).length==1)daha kısa olduğu görülüyor .
tsh 3'17

1
Ben düşünüyorum bu bir zamanda tüm sınır durumları (71 bayt) geçiyor.
Arnauld

2

Haskell , 57 53 bayt

x?y|let v!x=filter(==v)x==[v]=maximum[a|a<-x,a!x,a!y]

Çevrimiçi deneyin!

UPD: Teşekkürler @Likonik


Özellikle PPCG ve Haskell golf oynamalarına hoş geldiniz! Bu güzel bir ilk cevap! İki küçük şey: Ayrıca bir fek byte operatörü olarak ilan edebilir ve bazı baytları kaydetmek [1|...]==[1]yerine yazabilirsiniz sum[1|...]==1.
Laikoni

Koleksiyonumuz: Zaten onları görmedim durumda, burada ilginç olabilir bazı bağlantılar Haskell ipuçlarını golf , Haskell kuralları golf için rehber ve monad'ların ve İnsanlar , bizim Haskell sohbet odası.
Laikoni

1
In-astarı !ile andiki bayt kaydeder: çevrimiçi deneyin!
Laikoni

2

Wolfram Dili (Mathematica) , 40 bayt

Max@Cases[Tally@#⋂Tally@#2,{x_,1}:>x]&

Çevrimiçi deneyin!

Nasıl çalışır

Tally@#sayılarıyla birlikte ilk girdinin benzersiz öğelerinin bir listesini verir: örn. Tally[{2,2,2,6,3,5,8,2}]verim{{2,4},{6,1},{3,1},{5,1},{8,1}} . .

Tally@#2ikinci liste için de aynısını yapar ve her ikisinde de mevcut olan çiftleri bulur. Sonra Casesbiten çiftlerle birlikte seçeriz 1, sonuçta ilk elamanı alırız , bu bize tüm eşsiz ikizlerin bir listesini verir. Sonunda, Maxen büyük benzersiz ikizini döndürür.


2

Röda , 48 bayt

{m={|n|sort|count|[_]if[_=n]};[_()|m 1]|m 2|max}

Çevrimiçi deneyin!

Jq170727'nin jq cevabından ilham alındı .

Açıklama:

{ /* Anonymous function, takes input from the stream */
  m={|n|        /* Local function m with parameter n: */
    sort|count| /*   Count unique values in the stream */
    [_]if[_=n]  /*   For each value, push it to the stream if its count is n */
  };
  [      /* For each list in the stream: */
    _()| /*   Flat it (push its values to the stream) */
    m 1  /*   Push values that appear only once to the stream */
  ]|
  m 2|   /* Push values that appear twice to the stream */
  max    /* Find the max value in the stream */
}

2

F # (.NET Core) , 117 115 114 111 108 bayt

115 114 bayt

countByBu sefer başka bir çözüm :

let u x=x|>Seq.countBy id|>Seq.filter(fun a->snd a=1)|>Seq.map fst|>set
let f x y=Set.intersect(u x)(u y)|>Seq.max

Çevrimiçi deneyin!

117 111 bayt

let u x=x|>Seq.filter(fun a->x|>Seq.filter((=)a)|>Seq.length=1)|>set
let f x y=Set.intersect(u x)(u y)|>Seq.max

Çevrimiçi deneyin!

% 100 F #! Herhangi bir yardım açığız!

Ön ek notasyonu sayesinde 6 byte kazandı!

108 bayt

let f a b=Set.intersect(set a)(set b)|>Seq.filter(fun x->a@b|>Seq.filter(fun y->y=x)|>Seq.length<3)|>Seq.max

@concat işlevidir! Bu algoritma için teşekkür ederiz @ Ayb4btu.

Çevrimiçi deneyin!



2

Pip , 17 16 bayt

MX{_Na=_Nb=1FIa}

Bu iki listeyi argüman olarak alan bir fonksiyondur. Çevrimiçi deneyin!

açıklama

  {            }  Define function, args are a & b:
            FIa    Filter elements of a on this function:
   _Na              Count of element in a
      =_Nb          equals count of element in b
          =1        equals 1
                  This gives a function that returns a list of unique twins
MX                Modify it to take the max and return that instead

2

APL (Dyalog) , 18 karakter = 23 bayt *

Tam bir program gövdesi. STDIN’den gelen listelerin listesini ister. İstediğiniz sayıda liste ile çalışır. STDOUT çıkışları.

⌈/∊∩/{⊂⍺⍴⍨1=≢⍵}⌸¨⎕

Çevrimiçi deneyin!

 STDIN'den değerlendirilen girdi istemi

{}⌸¨ Her liste için, bu listedeki her benzersiz eleman için aşağıdaki fonksiyonu çağırınız, benzersiz elemanı sol argüman olarak ( ) ve meydana geldiği indislerin listesini sağ argüman olarak ( ) kullanınız:

≢⍵ endekslerin taklidi (örnek sayısı)

1= 1'e eşit

⍺⍴⍨ belirli öğeyi yeniden şekillendirmek için kullanın (yani benzersiz değilse boş liste verir)

Şimdi, her giriş listesi için iki benzersiz öğe listesine sahibiz (her öğe bir liste olmasına rağmen, benzersiz olmayan öğelerden kalan olarak boş listeler vardır).

∩/ kavşak (azaltma)

ε nlist (düzleştirmek)

⌈/ maksimum (azaltma)


* Klasik, sayım olarak ⎕U2338.


1

MATL , 13 bayt

,iSY'1=)]X&X>

Çevrimiçi deneyin! Veya Tüm test durumlarını doğrulayın .

açıklama

,      % Do twice
  i    %   Take input: array
  S    %   Sort array
  Y'   %   Run-length encode: pushes array of values and array of run lengths
  1=   %   Compare each run length with 1
  )    %   Use as logical index. This keeps only values that have appeared once
]      % End
X&     % Intersection of the two arrays
X>     % Maximum of array. Implicitly display

1

PHP, 98 bayt

<?foreach(($c=array_count_values)($_GET[a])as$a=>$n)$n-1||$c($_GET[b])[$a]-1||$a<$r||$r=$a;echo$r;

Dizileri GET parametresi olarak ave b.


Bu GET paramlarını sabitler için değiştirebileceğinizi düşünün.
Progrock

@Progrock Bu geçerli bir giriş yöntemi değil.
Titus

Soru, A ve B'nin diziler halinde verildiği cümleleridir. Ve herhangi bir makul girdi ve çıktı yöntemini söylüyor .... bu bağlantıyı kolayca takip edebildiğimden değil. Gerçekten tarifin gibi. (Eski Php 5.6'daki
boğulmalar

1

Java 8, 133 bayt

a->b->{long r;for(java.util.Collections c=null;;a.remove(r))if(b.contains(r=c.max(a))&c.frequency(a,r)*c.frequency(b,r)==1)return r;}

Açıklama:

Burada dene.

a->b->{                  // Method with two ArrayList<Long> parameters and long return-type
  long r;                //  Result-long
  for(java.util.Collections c=null; 
                         //  Create a java.util.Collections to save bytes
      ;                  //  Loop indefinitely
       a.remove(r))      //    After every iteration, remove the current item
    if(b.contains(r=c.max(a)) 
                         //   If the maximum value in `a` is present in `b`,
       &c.frequency(a,r)*c.frequency(b,r)==1)
                         //   and this maximum value is unique in both Lists:
      return r;          //    Return this value
                         //  End of loop (implicit / single-line body)
}                        // End of method

1

R , 73 bayt

function(A,B)max(setdiff(intersect(A,B),c(A[(d=duplicated)(A)],B[d(B)])))

Çevrimiçi deneyin!

Hesaplar Akesişir B, o ve yinelenen öğeler arasındaki farkın sonra maksimum Ave B.


1

JavaScript ES5, 122 121 114 bayt

function f(a,b){for(i=a.sort().length;--i+1;)if(a[i]!=a[i+1]&&a[i]!=a[i-1]&&!(b.split(a[i]).length-2))return a[i]}

Ben burada yeniyim, bu yüzden işlev tanımını kaldırabilir miyim ve sadece içeriğini ekleyebilir miyim (ki bu beni 17 bayt kurtarır).

İşte çalışan örnek: 122 121 114

122 - 121 bayt: a için sarma başlatma

121 ila 114 bayt: bbir dize olmalı


2
PPCG'ye Hoşgeldiniz! İşlev tanımını kaldıramazsınız, ancak bunun yerine bir lambda işlevi kullanabilirsiniz (JS'yi tanımıyorum, bu nedenle size yardımcı olamam).
Bay Xcoder

Bunu temizlediğin için teşekkürler. Lambda işlevlerinin herhangi bir karakteri kaydedebileceğini sanmıyorum, ancak deneyeceğim. Ayrıca, “Herhangi bir makul Girdi ve Çıktı yöntemine / biçimine izin veriliyor” dediğiniz için, bir dize olarak kabul bedip kaydedebilir b=''+b,miyim?
Piyin

JavaScript'i bilmesem de 115 bayta ulaşmayı başardım f=(a,b)=>{for(b=''+b,i=a.sort().length;--i+1;)if(a[i]!=a[i+1]&&a[i]!=a[i-1]&&!(b.split(a[i]).length-2))return a[i]}.
Bay Xcoder

1
Evet, bir dize girdisi iyi olacağından eminim
Bay Xcoder

Ancak bu ortaya çıkan JavaScript, ES6 değil ES5 olacaktır. Bir ES6 yanıtı zaten gönderildi, bu yüzden ES5'i gönderdim. Ve ikinci soruyu cevapladığınız için teşekkürler hehe
Piyin


1

Jq 1.5 , 76 bayt

def m(n):[.[indices(.[])|select(length==n)[]]]|unique[];[map(m(1))|m(2)]|max

Expanded

def m(n): # function to emit elements of multiplicity n
  [
    .[                         # select elements with
         indices(.[])          # number of indices in the array
       | select(length==n)[]   # equal to specified multiplicity
    ]
  ] | unique[]                 # emit deduped values
;

[
    map(m(1))   # collect multiplicity 1 elements from each array
  | m(2)        # collect multiplicity 2 elements
] | max         # choose largest of these elements

Çevrimiçi deneyin!

İşte aynı uzunluktaki başka bir çözüm:

def u:[keys[]as$k|[.[$k]]-(.[:$k]+.[$k+1:])]|add;map(u)|.[0]-(.[0]-.[1])|max

Expanded

def u: # compute unique elements of input array
  [
      keys[] as $k                   # for each index k
    | [.[$k]] - (.[:$k]+.[$k+1:])    # subtract other elements from [ .[k] ]
  ]                                  # resulting in [] if .[k] is a duplicate
  | add                              # collect remaining [ .[k] ] arrays
;
  map(u)                             # discard duplicates from each input array
| .[0]-(.[0]-.[1])                   # find common elements using set difference
| max                                # kepp largest element

Çevrimiçi deneyin!


1

APL, 47 bayt

{1↑R[⍒R←((1={+/⍵=A}¨A)/A←⍺)∩(1={+/⍵=B}¨B)/B←⍵]}

İki vektör alan, yinelenen öğeleri elimine eden, daha sonra sonuçların kesişimindeki en büyük öğeyi bulan isimsiz bir işlev bildirir.

A←⍺ve B←⍵işlev geçen verileri saklamak Ave B.

a=bher bir dizinde aeşit olduğu 1 olan bir vektör döndürür b. Eğer abir skaler ise (yani tekli bir niceliktir ve bir vektör değil), bu, elementin bolduğu her yerde 1 olan ave olmadığı zaman 0 olan bir vektör verir. Örneğin:

Input: 1=1 2 3
Output: 1 0 0

{+/⍵=A}: iç içe geçmiş anonim işlev; vektörün argümanının oluşumunu bulun Ave ekleyin, yani argümanın oluşum sayısını bulun.A

1={+/⍵=A}¨A: iç içe geçmiş anonim işlevi A'daki her bir öğeye uygulayın ve 1 yani benzersiz öğelere eşit olanları bulun

((1={+/⍵=A}¨A)/A←⍺): benzersiz elemanların yerini bulduktan sonra , sadece orijinal vektörde bu elemanları seçin ( /konumları sol argümanda 1'e karşılık gelen sağ argüman elemanlarından seçer)

R←((1={+/⍵=A}¨A)/A←⍺)∩(1={+/⍵=B}¨B)/B←⍵: İkinci argüman için işlemi tekrarlayın; Şimdi sadece benzersiz öğelere sahibiz, kesişimi, yani ortak elemanları bul ve bunu vektörde saklaR

R[⍒R]: Razalan sırayla elementlere eriş

1↑R[⍒R]: Razalan düzende sıralandığında ilk elemanı alın

Test durumu:

Input: 17 29 39 29 29 39 18 18 {1↑R[⍒R←((1={+/⍵=A}¨A)/A←⍺)∩(1={+/⍵=B}¨B)/B←⍵]} 19 19 18 20 17 18
Output: 17

1

J , 30 bayt

[:>./@,[*([*+/"1(1=*/)+/)@(=/)

Nasıl çalışır:

İki listenin çakıştığı yeri test etmeye başlıyorum =/(listelerin tüm üyeleri arasında eşitlik testi ekler:

   a =. 1 3 4 6 6 9
   b =. 8 7 6 3 4 3
   ]c=. a =/ b 
0 0 0 0 0 0
0 0 0 1 0 1
0 0 0 0 1 0
0 0 1 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0

Aynı sütundaki birden fazla 1, sayının sol argüman için benzersiz olmadığı anlamına gelir (bu durumda 6); satırda - doğru argüman için (3)

Daha sonra, kopyaların nerede olduğunu bulmak için tüm satırları ve tüm sütunları toplarım:

   +/ c
0 0 2 1 1 1
   +/"1 c
0 2 1 1 1 0

Yukarıdaki listelerin kartezyen ürününü buldum ve üyeleri 1'den 0'a daha büyük olarak belirledim.

    m =. (+/"1 c) (1=*/) +/c
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 1 1 1
0 0 0 1 1 1
0 0 0 1 1 1
0 0 0 0 0 0

Her iki listede de ortak olan benzersiz öğeleri bulmak için eşitlik matrisini m ile maskeleyip soldaki argümanı bununla çarptım.

]l =. a * m * c
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 4 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0

Sonra listeyi düzeltirim ve max elemanını bulurum:

 >./,l 
4

Çevrimiçi deneyin!


1

C # (.NET Core) , 66 + 31 = 97 65 + 31 = 96 bayt

a=>b=>a.Intersect(b).Where(x=>a.Concat(b).Count(y=>y==x)<3).Max()

Çevrimiçi deneyin!

İçin +31 bayt using System;using System.Linq;

@ Aloisdg'nin cevabından ilham aldım. Bununla birlikte, her iki dizide de benzersiz değerler aramak yerine, işlem sırasını ters çevirdim intersect, ilk önce bu olur ve ardından diziler birleştirildiğinde ve kesiştiği zaman iki kez oluşan öğelerin maksimum değerini buldum. kullanabilirim<3 olarak Counther iki dizide de olduğu gibi, herhangi bir değeri için, en az 2 olacaktır.

Teşekkür

@Aloisdg ve currying kullanımı önerisi sayesinde -1 bayt Func.


1
İyi fikir! Gerçekten beğendim
aloisdg diyor Reinstate Monica



0

Octave , 57 56 bayt

@(x)max(intersect(cellfun(@(x){x(sum(x'==x)==1)},x){:}))

Giriş olarak iki sayısal dizinin hücre dizisini alan anonim işlev.

Çevrimiçi deneyin!

açıklama

cellfun(@(x)...)İki giriş dizisinin her biri ( ) için bu, girişleri ( x.'==x) arasında ikili eşitlik karşılaştırması matrisi oluşturur ; keep ( x(...)) yalnızca sütun toplamının 1( sum(...)==1) olduğu girişleri ; ve sonucu bir hücreye ( {...}) yerleştirir. intersectİki sonucun ( {:}) kesişimi ( ) hesaplanır ve maksimum ( max(...)) alınır.


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.