Tekrar etmeyen ikinci karakter nedir?


18

Kod İncelemesinden gelen bu soruya dayanarak

Boş olmayan yazdırılabilir ASCII karakter dizisi verildiğinde, ikinci tekrarlanmayan karakteri çıktılayın. Örneğin, girdi için DEFDçıktı F.

Giriş

Çıktı

  • İkinci uygun bir biçimde tekrar, soldan sağa okurken, tekrar etmez karakteri.
  • Çıktı karakteri büyük / küçük harfe duyarlı değildir.
  • Böyle bir karakter yoksa (örneğin, tüm karakterler tekrar eder), boş bir dize çıktılayın.

kurallar

  • Algoritma durumu görmezden gelmelidir. Olduğu, bu Dve daynı karakter olarak sayılır.
  • Tam bir program veya bir işlev kabul edilebilir.
  • Giriş dizesinin boş olmadığı garanti edilecektir (en az bir karakter uzunluğunda).
  • Giriş dizesi ASCII'dir. Sadece alfasayısal değil, geçerli herhangi bir karakter de tekrarlanabilir (boşluklar dahil).
  • Standart boşluklar yasaktır.
  • Bu bu nedenle her zamanki golf kuralları geçerlidir ve en kısa kod (bayt cinsinden) kazanır.

Örnekler

Giriş ilk satırda, çıkış ikinci satırda.

DEFD
F

FEED
D

This is an example input sentence.
x

...,,,..,,!@
@

ABCDefgHijklMNOPqrsTuVWxyz
B

AAAAAABBBBB


Thisxthis


This this.
.

8
Büyük / küçük harfe duyarlı değilse, Forth'ta yapmayı düşünürdüm. Dize işlemleri bu dilde emilir.
mbomb007

Dilim küçük harfleri desteklemiyorsa ne olur?
Adám

@ Adám Farklı bir kod sayfası kullanıyor mu? Küçük harfleri desteklemiyorsa normalde ASCII dizesini nasıl girer?
AdmBorkBork

1
Aklımdaki sistemin 7 bit kod sayfası vardı; büyük harflerin küçük harfleri ve büyük harflerin glifler için kullanıldığı modifiye edilmiş standart kod sayfası. Bu, eski APL sistemlerinde yapıldı, böylece APL gliflerine erişmek için Shift kullanılabilirken, kaydırılmamış harfler klasik kodlama tarzı büyük harflerdi.
Adám

Yanıtlar:


10

MATL , 11 bayt

tk&=s1=)FT)

Tekrarlanamayan ikinci bir karakter yoksa, bu bir hata ile çıkar (varsayılan olarak izin verilir).

Çevrimiçi deneyin!

açıklama

t      % Implicitly take input string. Duplicate
k      % Convert to lowercase
&=     % 2D array of equality comparisons
s      % Sum of each column
1=     % True for entries that equal 1
)      % Apply logical index to the input string to keep non-repeated characters
TF)    % Apply logical index to take 2nd element if it exists. Implicitly display 

Ninja düzenlemesi yine grev yapıyor. : P
Dennis

@Dennis Hahaha. Sanırım yakında birkaç bayt kaldıracaksınız
Luis Mendo

10

Retina , 25 bayt

i!2=`(.)(?<!\1.+)(?!.*\1)

Çevrimiçi deneyin! (İlk satır, kodu birkaç girişten oluşan bir test paketinde çalıştırmayı sağlar.)

açıklama

Bu sadece tek bir normal ifade eşleşmesidir, normal ifade şu şekildedir:

(.)(?<!\1.+)(?!.*\1)

Yani, bir karakteri eşleştirin ve girişte başka hiçbir yerde görünmediğinden emin olun. Gerisi yapılandırma:

  • i büyük / küçük harf duyarsızlığını etkinleştirir.
  • ! Retina'ya maçları saymanın aksine yazdırmasını söyler.
  • 2= Retina'ya hepsinin aksine sadece ikinci maçı yazdırmasını söyler.

1
Bana öğrettiğin için teşekkürler 2=.
Leaky Nun

6

05AB1E, 15 12 bayt

l©v®y¢iy}}1@

Açıklaması

l©            # store lower case string in register
  v     }     # for each char in lower case string
   ®y¢iy      # if it occurs once in string, push it to stack
         }    # end if
          1@  # push the 2nd element from stack and implicitly display

Çevrimiçi deneyin

@Adnan sayesinde 3 bayt kaydedildi


Veya 12 bayt için l©v®y¢iy}}1@:).
Adnan

@Adnan: Güzel! @ Kullanmayı düşünmedim.
Emigna

5

Python 2, 59 58 bayt

Tek bir karakterin listesini veya çıktı yoksa boş bir listeyi döndürür. (Aptal büyük-küçük harf duyarsızlığı ...)

s=input().lower();print[c for c in s if s.count(c)<2][1:2]

Çevrimiçi deneyin



Geçerli bir girdi değil. Kullanıcı asla girdilerinden kaçmak zorunda kalmamalıdır.
mbomb007

4
Tabiki öyle. STDIN üzerinde dil listesi biçiminde listeler sunuyoruz. Dizeler neden farklı olsun ki?
Dennis

5

Jöle , 11 bayt

Œlµḟœ-Q$Ḋḣ1

Çevrimiçi deneyin! veya tüm test senaryolarını doğrulayın .

Nasıl çalışır

Œlµḟœ-Q$Ḋḣ1  Main link. Argument: s (string)

Œl           Convert s to lowercase.
  µ          Begin a new, monadic chain. Argument: s (lowercase string)
       $     Combine the two links to the left into a monadic chain.
      Q        Unique; yield the first occurrence of each character.
    œ-         Perform multiset subtraction, removing the last occurrence of each
               character.
   ḟ         Filterfalse; keep characters that do not appear in the difference.
        Ḋ    Dequeue; remove the first character.
         ḣ1  Head 1; remove everything but the first character.

4

Toplu, 171 bayt

@echo off
set a=.
set s=%~1
:l
if "%s%"=="" exit/b
set c=%s:~0,1%
call set t=%%s:%c%=%%
if "%s:~1%"=="%t%" set a=%a%%c%
set s=%t%
if "%a:~2%"=="" goto l
echo %c%

Alternatif formülasyon, ayrıca 171 bayt:

@echo off
set a=.
set s=%~1
:l
if "%s%"=="" exit/b
set c=%s:~0,1%
set t=%s:~1%
call set s=%%s:%c%=%%
if "%s%"=="%t%" set a=%a%%c%
if "%a:~2%"=="" goto l
echo %c%

W2008R2 üzerinde çalıştıramazsınız. "Call set ..." satırı "call set t =% s: D =%" olarak genişler ve "Komutun sözdizimi yanlış" mesajıyla iptal edilir.
meden

@meden Üzgünüm, bazı yazım hataları yazıma girdi. Ölü hediye post it söyledim daha kısa oldu! Şimdi düzeltildi.
Neil

3

Pyth, 16 15 bayt

@ Mbomb007 sayesinde 1 bayt

= Rz1.xhtfq1 / zTzk
= rz1: fq1 / zTz1 2

Test odası.


2
Pyth'i bile bilmiyorum, ama öyle diyorsan. : D
mbomb007

@ mbomb007 Biliyor musun, [1:2]hile.
Leaky Nun

Sen bir byte kaydedebilirsiniz t<…2yerine :…1 2. Sen taşıyarak başka byte kaydedebilirsiniz =rz1ayrıca değiştirirseniz, ilk kullanımına 1karşı Z(küçük harf yerine büyük çıkışı için): t<fq1/zT=rzZ2.
Anders Kaseorg

3

Aslında 19 bayt

;╗`ù╜ùc1=`░ε;(qq1@E

Çevrimiçi deneyin!

Açıklama:

;╗`ù╜ùc1=`░ε;(qq1@E
;╗                   push a copy of input to reg0
  `ù╜ùc1=`░          [v for v in s if
   ù╜ùc1=              s.lower().count(v.lower()) == 1]
           ε;(qq     append two empty strings to the list
                1@E  element at index 1 (second element)

3

C #, 129128 bayt

char c(string i){var s=i.Where((n,m)=>i.ToLower().Where(o=>o==Char.ToLower(n)).Count()<2).ToArray();return s.Length>1?s[1]:' ';}

iyi çalışıyor. Keşke her şeyi küçük harcamam gerekmeseydi


Bir argüman olarak "Thisxthis" geçirdiğimde bir IndexOutOfRangeException oluşturur. Bunun dışında == 1 <2 olarak değiştirilebilir düşünüyorum.
Yytsi

2

Linq ile C # lambda, 63 bayt

s=>(s=s.ToUpper()).Where(c=>s.Count(C=>c==C)<2).Skip(1).First()

Sen yerine gerekir .Skip(1).First()ile.ElementAt(1)
aloisdg eski haline Monica diyor

Daha da iyisi listeye .ToList()[1]
dönüşebilir

Bu, 2. konumda eşleşen bir karakterin olmadığı "", "AABB" ve "AABBC" gibi girişler için bir istisna atar. Sanırım FirstOrDefault'a ihtiyacınız var.
Grax32

2

C #, 141 bayt

void p(){var x=Console.ReadLine().ToLower();var c=0;foreach(char i in x){if(x.Split(i).Length-1<2){if(++c==2){Console.WriteLine(i);break;}}}}

Kesintisiz (en küçük), 135 bayt

void p(){var x=Console.ReadLine().ToLower();var c=0;foreach(char i in x){if(x.Split(i).Length-1<2){if(++c==2){Console.WriteLine(i);}}}}

(;;) ile birlikte, 150 bayt

void p(){for(;;){var x=Console.ReadLine().ToLower();var c=0;foreach(char i in x){if(x.Split(i).Length-1<2){if(++c==2){Console.WriteLine(i);break;}}}}}

Yorum yapılmamış

void p()
{
    var x=Console.ReadLine().ToLower();//Get lowercase version of input from STDIN
    var c=0; //Create "count" integer
    foreach(char i in x){//For each char in input from STDIN
        if(x.Split(i).Length-1<2)//If current char occurs once in input from STDIN
        {
            if(++c==2){ //Add 1 to count and if count is 2
                Console.WriteLine(i); //Print result to STDOUT
                break; //Exit foreach
            } //End of IF
         } //End of IF
     } //End of FOREACH
} //End of VOID

TuukkaX tarafından kaydedilen 12 bayt (sayımı c olarak değiştirin).

TuukkaX tarafından kaydedilen 3 bayt (dizeyi var olarak değiştir).

TuukkaX tarafından "With for (;;)" içine kaydedilen 4 bayt ((true) iken (;;) olarak değiştirildi).

TuukkaX tarafından kaydedilen 2 bayt (c ++; if (c == 2) olarak if (++ c == 2) olarak değiştirildi).

Bryce Wagner tarafından kaydedilen 14 bayt (x.ToCharArray () öğesini x olarak değiştirildi).


@TuukkaX oh, gerçekten. teşekkür ederim!
r3pear

PPCG'ye Hoşgeldiniz! Bu güzel bir ilk gönderi! Kurallar, bu soruna cevapların işlevler veya tam programlar olması gerektiğinden bahsettiğinden, kodlarınız küçük değişiklikler gerektirir. Baytları, varyerine yerine kullanarak stringve cyerine bir şeye sahip olarak da kaydedebilirsiniz count.
Yytsi

@TuukkaX Tekrar teşekkürler! Kısaca kodu değiştireceğim ve dizeyi var olarak değiştireceğim.
r3pear

@TuukkaX void program () {} ??? gibi bir şey eklemem gerekir mi?
r3pear

Evet, ancak bayt kaydetmek için bir bayt işlev adı verin! :)
Yytsi

2

x86 makine kodu, 43 bayt

Onaltılı olarak:

FC31C031C95641AC84C0740E3C6172F63C7A77F28066FFDFEBEC5EAC49740B89F751F2AE5974F44A77F1C3

İşlev, (E) SI'daki giriş dizesine bir işaretçi ve (E) DX'deki bir tamsayıyı alır ve böyle bir karakter yoksa (E) DX-th yinelenmeyen karakterini veya sıfır değerini döndürür. Bir yan etki olarak, dizeyi büyük harfe dönüştürür.

demontaj:

fc             cld
31 c0          xor    eax,eax
31 c9          xor    ecx,ecx
56             push   esi
_loop0:                         ;Search for the NULL char,
41             inc    ecx       ;counting the length in the process
ac             lodsb
84 c0          test   al,al
74 0e          je     _break0   ;NULL found, break
3c 61          cmp    al,0x61   ;If char is
72 f6          jb     _loop0    ;between 'a' and 'z'
3c 7a          cmp    al,0x7a   ;convert this char
77 f2          ja     _loop0    ;to uppercase in-place
80 66 ff df    and    byte ptr [esi-0x1],0xdf
eb ec          jmp    _loop0
_break0:
5e             pop    esi       ;Reset pointer to the string
_loop:                          ;ECX=string length with NULL
ac             lodsb            ;Load next char to AL
49             dec    ecx
74 0b          je     _ret      ;End of string found, break (AL==0)
89 f7          mov    edi,esi   ;EDI points to the next char
51             push   ecx
f2 ae          repnz scasb      ;Search for AL in the rest of the string
59             pop    ecx
74 f4          je     _loop     ;ZF==1 <=> another instance found, continue
4a             dec    edx
77 f1          ja     _loop     ;If not yet the EDX-th non-rep char, continue
_ret:
c3             ret

2

APL, 32 bayt

{⊃1↓⍵/⍨1=+/∘.=⍨(⎕UCS ⍵)+32×⍵∊⎕A}

Deneyin || Tüm test örnekleri

Açıklama:

                (⎕UCS ⍵)+32×⍵∊⎕A  Add 32 to uppercase letters
            ∘.=⍨                    Make an equality matrix
          +/                        Check how many matches
    ⍵/⍨1=                           Keep elements with 1 match
  1↓                                Drop the first one
⊃                                   Return the second one

16 bayt ile göndermek üzereydim, ama büyük / küçük harfe duyarsız olması gerektiğini fark ettim ...


1
(⎕UCS ⍵)+32×⍵∊⎕A819⌶⍵
18:45

Bu operatörü daha önce hiç görmedim. Hangi sürümde çalışıyor?
Woofmao

Buna i-ışını denir . Dyalog APL'nin tüm versiyonlarında operatördür. Başlangıçta IBM'in özel çağrıları için IBM APL'nin eski sürümlerinde kullanılan bir işlevdi. Anla? IBM - i-beam ?
Adam

Genel olarak ve hizmet için belgeler 819 ("819" ≈ "Büyük"). Çevrimiçi deneyin!
Adam

Yeni bir şey öğrendim. tryapl.org bunu tanımıyor gibi görünüyor, bu yüzden sadece TIO bağlantınızı kullanmamın bir sakıncası var mı?
Woofmao


1

Mathematica, 49 bayt

Cases[Tally@ToUpperCase@#,{_,1}][[2,1]]~Check~""&

Anonim işlev. Girdi olarak karakterlerin bir listesini alır. Oluşturulan hataları yoksayın.


1

JavaScript (Firefox 48 veya öncesi), 60 bayt

f=s=>(m=s.match(/(.).*\1/i))?f(s.replace(m[1],"","gi")):s[1]

undefinedYalnızca sıfır veya bir yinelenmeyen karakter varsa döndürür . Dizede bir kereden fazla görünen tüm karakter oluşumlarını büyük / küçük harfe duyarlı olmayan şekilde silerek çalışır. Firefox 49'da kaldırılan standart dışı bir Firefox uzantısına dayanır. 119 91 bayt ES6 sürümü:

f=s=>(m=s.match(/(.).*?(\1)(.*\1)?/i))?f((m[3]?s:s.replace(m[2],"")).replace(m[1],"")):s[1]

Dizede en az iki kez görünen tüm karakterleri özyinelemeli olarak arar. Karakter tam olarak iki kez görünürse, her iki olay da silinir, aksi takdirde yalnızca ilk olay silinir (diğer olaylar daha sonra silinir). Bu, olayların bir fark durumuna sahip olmasını sağlar.


Ben aslında değiştirerek ES6 uyumlu olması Firefox 48 cevap uyarlayabilirsiniz inanıyoruz m[1]ilenew RegExp(`${m[1]}`,"gi")
Değer Ink

@ KevinLau-notKenny Bu, özel karakterler için işe yaramazdı ve maalesef 93'e kadar götürmek için özel durumları bana 33 bayta mal etti.
Neil

noooooo özel karakterler değil! Şimdi onlara cevap verebilmek için Ruby yanıtımı düzenlemek zorunda kaldım.
Değer Mürekkebi

1

J, 25 bayt

(1{2{.]-.]#~1-~:)@tolower

kullanım

   f =: (1{2{.]-.]#~1-~:)@tolower
   f 'DEFD'
f
   f 'FEED'
d
   f 'This is an example input sentence.'
x
   f '...,,,..,,!@'
@
   f 'ABCDefgHijklMNOPqrsTuVWxyz'
b
   f 'AAAAAABBBBB'

   f 'Thisxthis'

   f 'This this.'
.

açıklama

(1{2{.]-.]#~1-~:)@tolower  Input: s
                  tolower  Converts the string s to lowercase
              ~:           Mark the indices where the first time a char appears
            1-             Complement it
         ]                 Identity function to get s
          #~               Copy only the chars appearing more than once
      ]                    Identity function to get s
       -.                  Remove all the chars from s appearing more than once
   2{.                     Take the first 2 chars from the result (pad with empty string)
 1{                        Take the second char at index 1 and return it

1

Bash, 58 bayt

tr A-Z a-z>t
tr -dc "`fold -1<t|sort|uniq -u`"<t|cut -c2

Dikkat: Bu, t adlı geçici bir dosya oluşturur . Zaten mevcutsa, üzerine yazılır.


1

C, 174 bayt

int c(char*s){int y=128,z=256,c[384],t;memset(c,0,z*6);for(;t=toupper(*s);s++){c[t]++?c[t]-2?0:c[z+(c[y+c[z+t]]=c[y+t])]=c[z+t]:c[z]=c[y+(c[z+t]=c[z])]=t;}return c[y+c[y]];}

Bu en kısa değil, oldukça etkili bir uygulamadır. Temelde, sıralı aday karakter setini korumak için çift bağlantılı liste kullanır ve giriş dizesini yalnızca bir kez tarar. Karakter kodu veya sıfır bulunmazsa döndürür.

Biraz çözülmemiş versiyon:

int c(char*s)
{
    int y=128,z=256,c[384],t;
    //It's basically c[3][128], but with linear array the code is shorter

    memset(c,0,z*6);

    for(;t=toupper(*s);s++)
    {
        c[t]++ ?        // c[0][x] - number of char x's occurrence
            c[t] - 2 ?  // > 0
                0       // > 1 - nothing to do  
                : c[z + (c[y + c[z + t]] = c[y + t])] = c[z + t]  // == 1 - remove char from the list
            : c[z] = c[y + (c[z + t] = c[z])] = t; // == 0 - add char to the end of the list
    }
    return c[y + c[y]];
}

1

C #, 143 bayt

char c(string s){var l=s.Select(o=>Char.ToLower(o)).GroupBy(x=>x).Where(n=>n.Count()<2).Select(m=>m.Key).ToList();return l.Count()>1?l[1]:' ';}

1

TSQL, 128 bayt

golfed:

DECLARE @ varchar(99)=',,zzzbb@kkkkkkJgg'

,@i INT=99WHILE @i>1SELECT
@i-=1,@=IIF(LEN(@)>LEN(x)+1,x,@)FROM(SELECT
REPLACE(@,SUBSTRING(@,@i,1),'')x)x PRINT SUBSTRING(@,2,1)

Ungolfed:

DECLARE @ varchar(99)=',,zzzbb@kkkkkkJgg'

,@i INT=99

WHILE @i>1
  SELECT
    @i-=1,@=IIF(LEN(@)>LEN(x)+1,x,@)
  FROM
    (SELECT 
       REPLACE(@,SUBSTRING(@,@i,1),'')x
    )x

PRINT SUBSTRING(@,2,1)

Vaktini boşa harcamak


1

Yakut, 53 bayt

Giriş STDIN, çıkış STDOUT. Ruby'de, bir dizideki veya dizedeki dizin dışı pozisyonlar nilyazdırılmaz.

String#countRuby'de garip bir işlevdir, çünkü geçirilen dize için yineleme sayısını saymak yerine, o dizedeki her harf için yineleme sayısını sayar. Genellikle sinir bozucu ama bu sefer kendi yararımıza kullanabiliriz.String#swapcasebüyük ve küçük harfleri değiştirir.

$><<gets.chars.reject{|c|$_.count(c+c.swapcase)>1}[1]

.46 bayt gibi özel karakterlere karşı güvenli olmayan eski sürüm

$><<gets.chars.reject{|c|$_=~/#{c}.*#{c}/i}[1]

1

Java 8, 172156 bayt

(String s)->{s=s.toLowerCase();for(char i=0,c;s.length()>0;s=s.replace(c+"","")){c=s.charAt(0);if(!s.matches(".*"+c+".*"+c+".*")&&++i>1)return c;}return' ';}

-15 bayt .. Dang o zaman golf oynamakta kötüydüm. ;)

Açıklama:

Burada deneyin.

(String s)->{                          // Method with String parameter and character return-type
  s=s.toLowerCase();                   // Make the input-String lowercase
  for(char i=0,c;s.length()>0;         // Loop over the characters of `s`
      s=s.replace(c+"","")){           // And after every iteration, remove all occurrences of the previous iteration
    c=s.charAt(0);                     // Get the current first character
    if(!s.matches(".*"+c+".*"+c+".*")  // If it doesn't occur more than once
     &&++i>1)                          // And this was the second one we've found
      return c;                        // Return this second characters
  }                                    // End of loop
  return' ';                           // Else: return an empty character/nothing
}                                      // End of method

1

R , 79 bayt

function(z){y=tolower(el(strsplit(z,"")));x=table(y);y[y%in%names(x[x==1])][2]}

Çevrimiçi deneyin!

Kesinlikle burada bir şey golf olabilir gibi hissediyorum. Ama bu zorluktan gerçekten keyif aldım.

Bu cevap, dizeyi bir karakter vektörüne böler, hepsini küçük harfe dönüştürür ve tablolar (sayar). Bir kez oluşan karakterler seçilir ve yukarıda belirtilen vektör içindeki karakterlerle karşılaştırılırsa, doğru olan ikinci değer çıktı olarak döndürülür. Boş bir dize veya yinelenen karakter içermeyen bir dize NA çıktısı verir.



1

K (oK) / K4 , 11 bayt

Çözüm:

*1_&1=#:'=_

Çevrimiçi deneyin!

Açıklama:

*1_&1=#:'=_ / the solution
          _ / convert input to lowercase
         =  / group alike characters
      #:'   / count (#:) each group
    1=      / 1 equal to length of the group?
   &        / where true
 1_         / drop the first
*           / take the first


0

Perl, 75 bayt

 my$s=<>;chomp$s;my$c;for my$i(split//,$s){my$m=@{[$s=~/$i/gi]};$m<2and++$c>=2and say$i and last}

0

Javascript (harici Kütüphane kullanılarak) (107 bayt)

Yazdığım bir kütüphaneyi kullanarak bunu ezdim. Söz konusu dize olan "s" değişkeninin bildirimini saymam gerekip gerekmediğinden emin değilim.

(s)=>_.From(s).ToLookup(y=>y.toLowerCase(),z=>z).Where(g=>g.Value.Count()==1).Select(x=>x.Key).ElementAt(1)

Bu, boş bir dize girişini, yalnızca bir yinelenmeyen karaktere sahip bir girişi ve 2+ yinelenmeyen karaktere sahip bir girdiyi işleyecektir

Image 1


Söz konusu kütüphaneye bir bağlantınız var mı? Ayrıca, bu kod golf olmak, yapabileceğiniz beyaz alan çıkarmak zorunda
Value Ink

Hey, evet github.com/mvegh1/Enumerable . Henüz doküman yok. Maalesef, beyaz alanı azaltmak için bu cevabı temizleyeceğim
applejacks01

Muhtemelen cevaplama metninde belirtmeli ve bağlantı kurmalısınız. Ayrıca, bayt hesabı ile ilgili fikir birliği, anonim bir lambda (yani s=> ...) koymaktır
Value Ink

Tamam sorun değil. Kodumu bağlayarak kimseyi rahatsız etmek istemedim, ama kütüphanemi kullandığımı söylemiştim. Cevabımı lambda ile güncelleyeceğim, bana
bildirdiğiniz

0

Clojure, 109 bayt

#(let[s(clojure.string/lower-case %)](or(second(remove(set(map(fn[[k v]](if(> v 1)k))(frequencies s)))s))""))

Umarım daha özlü bir yol vardı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.