プレフィックスのテキストを検索し、テキスト内のすべてのサフィックスをリストします


17

ここでは、「接頭辞に続く任意の部分文字列」を意味するために、「接尾辞」を大まかに使用します。

ここでの「プレフィックス」とは、単語の開始を意味します。単語の開始は、スペースの後または入力テキストの最初の文字(最初の単語)として定義されます。単語の途中にある「プレフィックス」は無視されます。

たとえば、入力プレフィックスが「arm」で、入力テキストが「迫り来るハルマゲドンに対してダンブルドアの軍隊が完全に武装した」場合、出力リストには(y、ed、ageddon)が含まれます。

テストケース

大文字と小文字が区別され、文字列はスペースの後に終わると仮定します。入力はスペースで始まりません。

重複の削除はオプションです。


Input prefix: "1"

Input text:

"He1in aosl 1ll j21j 1lj2j 1lj2 1ll l1j2i"

Output: (ll, lj2j, lj2) - in any permutation

Input prefix: "frac"

Input text: 

"fracking fractals fracted fractional currency fractionally fractioned into fractious fractostratic fractures causing quite a fracas"

Output: (king, tals, ted, tional, tionally, tioned, tious, tostratic, tures, as)

Input prefix: "href="https://www.astrotheme.com/astrology/"

Input text: 

"(div style="padding: 0; background: url('https://www.astrotheme.com/images/site/arrondi_450_hd.png') no-repeat; text-align: left; font-weight: bold; width: 450px; height: 36px")
  (div class="titreFiche" style="padding: 5px 0 0 6px")(a href="https://www.astrotheme.com/astrology/Nolwenn_Leroy" title="Nolwenn Leroy: Astrology, birth chart, horoscope and astrological portrait")Nolwenn Leroy(br /)
(/div)
  (div style="text-align: right; border-left: 1px solid #b2c1e2; border-right: 1px solid #b2c1e2; width: 446px; padding: 1px 1px 0; background: #eff8ff")
    (table style="width: 100%")(tr)(td style="width: 220px")
(div style="padding: 0; background: url('https://www.astrotheme.com/images/site/arrondi_450_hd.png') no-repeat; text-align: left; font-weight: bold; width: 450px; height: 36px")
  (div class="titreFiche" style="padding: 5px 0 0 6px")(a href="https://www.astrotheme.com/astrology/Kim_Kardashian" title="Kim Kardashian: Astrology, birth chart, horoscope and astrological portrait")Kim Kardashian(br /)(span style="font-weight: normal; font-size: 11px")Display her detailed horoscope and birth chart(/span)(/a)(/div)
(/div)
(div style="padding: 0; background: url('https://www.astrotheme.com/images/site/arrondi_450_hd.png') no-repeat; text-align: left; font-weight: bold; width: 450px; height: 36px")
  (div class="titreFiche" style="padding: 5px 0 0 6px")(a href="https://www.astrotheme.com/astrology/Julia_Roberts" title="Julia Roberts: Astrology, birth chart, horoscope and astrological portrait")Julia Roberts(br /)(span style="font-weight: normal; font-size: 11px")Display her detailed horoscope and birth chart(/span)(/a)(/div)
    (td id="cfcXkw9aycuj35h" style="text-align: right")
  (/div)"

Output: (Nolwenn_Leroy", Kim_Kardashian", Julia_Roberts")

勝者

これはであるため、最も少ないバイトが勝ちます。:)

コードがテストケースのような任意の問題を解決できる限り、動作する任意の方法で入力を受け入れることができます。


2
明確にするために、接頭辞は単語の先頭になければなりませんか?2番目のテストケースに「diffraction」という単語が含まれていた場合、出力は変わりますか?
スンダ

2
https://www.astrotheme.com/astrology/前にある場合、どのようにしてプレフィックスにすることができますhref="か?
ニール

1
接尾辞は空にできますか?
user202729

1
とにかくそうするように見えるスペースと同様に、他のホワイトスペースで人々が分割できるようにすることをお勧めします。また、入力の行に複数のスペースが含まれないようにすることをお勧めします(または、空の単語が未定義の動作を引き起こす可能性があることをいくらか同等に)。チャレンジの主な部分は単語部分に分割することではないため、これらの両方をお勧めします(単語のリストまたは単に単語を入力として許可することをお勧めしますが、22の答えがあり、遅すぎます-注意することただし、将来の課題に備えて)。
ジョナサンアラン

1
-1で、他の空白での分割が可能になりました。チャレンジが元々あったことは理にかなっていますが、今変更すると、答えが2つの異なることを行うものに分割されます。そして、これはいくつかの言語で処理できない場合とは異なります。ここでは、64ビットの数値などが、わずかに(おそらく)より複雑な一致を実装することを意味するため、誤った仮定で答えを修正し、おそらくこれを確認するためのテストケースを追加する方が理にかなっています。
スンダ-モニカを復元18年

回答:


5

R、63バイト

function(s,p,z=el(strsplit(s,' ')))sub(p,'',z[startsWith(z,p)])

オンラインでお試しください!

ポジティブルックビハインドの実装は、非常に大きなregmatches/gregexpr組み合わせのため、残念ながら5バイト長くなります。

function(s,p)regmatches(s,gregexpr(paste0('(?<=',p,')[^ ]*'),s,,T))

2
素朴なsub(grep())は、66の後ろ読みよりもわずかに優れていますが、startsWith()に侵入しません。アプローチを変更しない限り、ここで改善する余地はあまりありません。オンラインでお試しください!
CriminallyVulgar

4

ゼリー、12バイト

Ḳfṛ"€¥Ḋ€ṫ€L}

オンラインでお試しください!


芸術作品。: ')これを使用してHTMLをリストに解析します。ありがとうございました。:)
DrQuarius


にはうまくいくようです。なぜか分からない?
DrQuarius

1
@DrQuariusこれは有名なジョークで、user202729が拡張しました。
エリックアウトゴルファー

4

Japt、9バイト

入力を単語の配列として取得できる場合は8バイト。

¸kbV msVl
¸         // Shorthand for `qS`, split into words.
 kbV      // Filter the words, selecting only those that start with the prefix.
     msVl // For each remaining word, remove prefix length chars from the start.

オンラインでお試しください!


とてもいいですが、最後のテストケースではうまくいかないようです。文字列内の引用符による可能性がありますか?または新しい行?
DrQuarius

@DrQuarius最後のテストケースに問題がありますか?探している文字列はすべて単語の中央にあり(で囲まれていますurl(''))、いずれも先頭にありません。
Nit


4

C(GCC) 113の 109 106 105バイト

@LambdaBetaのおかげで-4バイト!
@WindmillCookiesのおかげで-3バイト!

i;f(char*s,char*t){for(i=strlen(s);*t;t++)if(!strncmp(t,s,i))for(t+=i,puts("");*t^32&&*t;)putchar(*t++);}

オンラインでお試しください!


1
両方を削除すると、4バイト節約できます^0。ジャスト;*t;アンド&&*t;
LambdaBeta

@LambdaBetaありがとう!私は逃しました。
betseg

1
別の戦略を使用して107まで下げることができました。ごめんなさい:)
LambdaBeta

@LambdaBeta私は実際にその方法を考えましたが、私が投稿したソリューションよりも短いとは思いませんでした。いい答えです。
betseg

1
:代わりのputcharの使用プット、今107、別の行に出力されtio.run/...
風車クッキー

3

Japt16 12バイト

アーナルド港の回答

@Shaggyから-4バイト

iS qS+V Å®¸g

iS                  Insert S value (S = " ") at beginning of first input (Implicit)
   q                split using
    S+V             S + Second input
        Å           slice 1
         ®          map
          ¸         split using S
           g        get first position

オンラインでお試しください!



おそらくこれがArnauldのソリューションの移植であることに言及する必要があります。(もちろん、それが独立して派生したものではないと仮定して)
シャギー

@Shaggy正直なところ、これが同じ答えだとは気づかなかったが、とにかく彼にクレジットをあげる。ごめんなさい
ルイス・フェリペ・デ・イエス・ムニョス

試してみたい場合は、9バイトの解決策があります。
シャギー

@Shaggy これを言ったのですか、それとも何か違うことを考えていたのですか?
Nit

3

05AB1E、11バイト

#ʒηså}εsgF¦

オンラインでお試しください!ここに複数行の文字列のデモがあります)

どのように機能しますか?

#ʒηså} εsgF¦完全なプログラム。
#最初の入力をスペースで分割します。
 ʒ}単語をフィルターする...
  ηså...「2番目の入力は単語の接頭辞で発生しますか?」
      εそして、有効な単語ごとに
       sg 2番目の入力の長さを取得します。
         F¦そして、その回数だけ単語の最初の文字をドロップします。

:)非常に素晴らしい、複数行デモに感謝します!他のプログラムに問題を引き起こしていたと思います。
-DrQuarius

3

スタックス、8 バイト

·B¬╤²*6&

実行してデバッグする

説明:

j{x:[fmx|- Full program, implicit input: On stack in order, 1st input in X register
j          Split string on spaces
 {   f     Filter:
  x:[        Is X a prefix?
      m    Map passing elements:
       x|-   Remove all characters in X the first time they occur in the element
             Implicit output

x%t(Xの長さ、左からトリム)を使用することもできます。これも同様に長いですが、9バイトにパックします


綺麗な。:)これが勝者になると思います。最も低いバイトスコアの競合のほとんどは、3番目のテストケースを解析できませんでした。:)
DrQuarius

ああ...しかし、私はあなたがそれをどうやってやったかわかります、文字列内の引用符がプログラムの一部ではないことをプログラムに知らせる必要がありました。大丈夫だと思います。また、あなたのものはとにかく最短です。:)
DrQuarius

3

網膜、31バイト

L`(?<=^\2¶(.|¶)*([^ ¶]+))[^ ¶]+

オンラインでお試しください!最初の行は目的のプレフィックスで、残りは入力テキストです。重複を削除しません。空白が有効な区切り文字である場合、25バイトになります。説明:有効な接頭部の接尾部をリストします。は[^ ¶]+、サフィックス自体に一致します。正規表現のプレフィックスは、サフィックスのプレフィックスが入力プレフィックスであることを保証する後読みです。後読みは右から左に評価されるため、これは接頭辞(同じパターンを使用し()てキャプチャするためにs 内で)を照合することから始まり、次に入力の先頭で独自の行の接頭辞を照合する前に任意の文字を照合します。


空白はスペースや改行を意味しますか?そうだとすればそれは有効な解決策だと思いますが、すべての人に公平を期すために、述べたように問題を残します。
DrQuarius

@DrQuariusいいえ、空白にはタブ、フォームフィード、さらには楕円が含まれます
ニール

Retinaは、投稿を見たときに思いついた最初の言語でした(まだその言語はわかりません)。でももっと短くなると思った。説明が必要ですか?例えば ドキュメントは改行文字であると言っていますが、ここでなぜそんなに多くが必要なのかわかりません。
スンダ

@sundar申し訳ありませんが、その時はちょっと急いでいました。最初は、最初の行全体がプレフィックスに一致することを保証します。2番目の行は、中間行の数が不明なために必要です。最後の2つは同じように機能します-否定された文字クラスは通常改行を含みますが、ここではそれを望みません。
ニール

問題なく、追加してくれてありがとう。「通常は改行を含めますが、ここには必要ありません」<-正しく理解できれば、ここに必要です。OPは、スペースのみが区切り文字としてカウントされ、プレフィックスがスペースで始まり、サフィックスがスペースで終わることを厳密に指定します。例えば 「dif \ nfractional」は「frac」と一致しません。これは、プレフィックスがスペースではなく改行の後に来るためです。同様に、「fracture- \ nrelated」は接尾辞「ture- \ nrelated」を返す必要があります。少なくとも1つ、おそらくそれ以上を削除できるので、これは良いニュースです。
スンダ-復活モニカ

3

Brachylog24 21バイト

tṇ₁W&h;Wz{tR&h;.cR∧}ˢ

オンラインでお試しください!

インライン述部と変数を共有している場合、数バイト短くなる可能性があります。

入力は、最初の要素としてプレフィックスを、2番目の要素としてテキストを含む配列です。

tṇ₁W                    % Split the text at spaces, call that W
    &h;Wz               % Zip the prefix with each word, to give a list of pairs
         {         }ˢ   % Select the outputs where this predicate succeeds:
          tR            % Call the current word R
            &h;.c       % The prefix and the output concatenated
                 R      % should be R
                  ∧     % (No more constraints on output)

2

IBM / Lotus Notesフォーミュラ、54バイト

c:=@Explode(b);@Trim(@If(@Begins(c;a);@Right(c;a);""))

aand という名前の2つのフィールドからの入力を受け取りますb。これは、Formulaが@Forループを必要とせずに関数をリストに再帰的に適用するためです。

TIOが利用できないため、スクリーンショットを次に示します。

ここに画像の説明を入力してください


2

APL(Dyalog Unicode)、23 バイトSBCS

完全なプログラム。stdinからのテキストとプレフィックスの入力を求めます。リストを標準出力に出力します。

(5'(\w+)\b',⎕)⎕S'\1'⊢⎕

オンラインでお試しください!

 プロンプト(テキスト用)

 その結果('\1'から分離

()⎕S'\1' PCRE次の正規表現からキャプチャグループ1のリストを検索して返します。

 プロンプト(プレフィックスの場合)

'(\w+)\b', この文字列を先頭に追加します(単語文字のグループとそれに続く単語境界)

5⌽ 最初の5文字を​​最後まで回転します。 '\bPREFIX(\w+)'


2

C(clang)、107バイト

i;f(s,t,_)char*s,*t,*_;{i=strlen(s);_=strtok(t," ");while((strncmp(_,s,i)||puts(_+i))&&(_=strtok(0," ")));}

オンラインでお試しください!

説明:

i;f(s,t,_)char*s,*t,*_;{   // F takes s and t and uses i (int) and s,t,u (char*)
    i=strlen(s);           // save strlen(s) in i
    _=strtok(t," ");       // set _ to the first word of t
    while(                 // while loop
        (strncmp(_,s,i)||  // short-circuited if (if _ doesn't match s to i places)
         puts(_+i))        // print _ starting at the i'th character
        &&                 // the previous expression always returns true
        (_=strtok(0," "))) // set _ to the next word of t
    ;                      // do nothing in the actual loop
}

strccの#include <string.h>問題が原因でgccがセグメンテーション違反になるため、clangにする必要があります。



2

MATL、17バイト

Yb94ih'(.*)'h6&XX

MATL Onlineでお試しください

どうやって?

Yb -入力をスペースで分割し、結果をセル配列に配置します

94- ASCIIコード^の文字

ih -入力(「frac」など)を取得し、「^」と入力を連結します

'(.*)'h-文字列'(.*)'をスタックにプッシュし、「^ frac」と「(。*)」を連結します。これ'^frac(.*)で、文字列の先頭で「frac」に一致し、その後に続くものをすべてキャプチャする正規表現ができました。

6&XX- 6&「トークン」モードを指定して、正規表現マッチングを実行します。つまり、一致全体ではなく、一致したキャプチャグループが返されます。

結果を暗黙的に出力します。


それがそう'Tokens'です。知っておきたい!
ルイスメンドー

1
ハハ。私もわからなかった、この答えの試行錯誤によってそれを理解しました。
スンダ


2

PowerShellの3.0、60の 62 59バイト

param($p,$s)-split$s|%{if($_-cmatch"^$p(.*)"){$Matches[1]}}

cmatch出力を抑制するいくつかのバイトを失いました。意図的に重複を引き起こすことにより、いくつかを得たジャンキーなソリューションがありました。しかし、それが最初のものと一致しなかった場合にもレッドラインを投げましたが、私はそれについて考えるので今ではうまくありません。ただし、修正するには+2バイト。


60バイトのソリューションは、場合によっては二重回答を返しking, tals, ted, tional, tional, tionally, tioned, tioned, tious, tostratic, tures,tures,tures, tures, asHe1in例でインデックスエラーを示します。Powershell 5.1、6.0.2。62バイトのソリューションはOKです。
mazzy

1
@mazzy知っていましたが、「重複は許可されています」ビットを悪用して、一致しない場合にさらに重複を返し、一致しない最初の反復で赤をスローするようにしました。
ヴェスカー




1

、11バイト

Haskellの答えのほんの一部です。

m↓L⁰foΠz=⁰w

オンラインでお試しください!

説明

m↓L⁰f(Πz=⁰)w  -- prefix is explicit argument ⁰, the other one implicit. eg: ⁰ = "ab" and implicit "abc def"
           w  -- words: ["abc","def"]
    f(    )   -- filter by (example w/ "abc"
       z=⁰    -- | zip ⁰ and element with equality: [1,1]
      Π       -- | product: 1
              -- : ["abc"]
m             -- map the following
 ↓            -- | drop n elements
  L⁰          -- | n being the length of ⁰ (2)
              -- : ["c"]

1

ゼリー 11  9 バイト

Ḳœṣ€ḢÐḟj€

左側のテキスト(文字のリスト)と右側の接頭辞(文字のリスト)を受け入れるダイアディックリンク。文字のリスト(結果として生じる接尾辞)のリストを生成します。

オンラインでお試しください!(フッターはスペースで結合して、プログラム全体の暗黙的なスマッシングを回避します)
注:OPの文字列に3つのエッジケースを追加しました-最初に非フラクタルおよびnofracfracheremateを出力し、フラクシットを出力する必要があります。

どうやって?

Ḳœṣ€ḢÐḟj€ - Link: text, prefix                        e.g. "fracfracit unfracked", "frac"
Ḳ         - split (text) at spaces -> list of words        ["fracfracit", "unfracked"]
   €      - for each (word):
 œṣ       -   split around sublists equal to (prefix)       ["","","it"]  ["un","ked"]
     Ðḟ   - filter discard items for which this is truthy:
    Ḣ     -   head
          -   -- Crucially this modifies the list:             ["","it"]       ["ked"]
          -   -- and yields the popped item:                 ""            "un"
          -   -- and only non-empty lists are truthy:       kept          discarded
          -            ...so we end up with the list:      [["","it"]]
        € - for each (remaining list of lists of characters):
       j  -   join with the prefix                          "fracit"                                             
          -                                                ["fracit"]

前の11バイト:

Ḳs€L}Ḣ⁼¥ƇẎ€

上記のようなダイアディックリンクも。

オンラインでお試しください!


1

Perl 5、-asE、23 22 21バイト(?)

say/^$b(.*)/ for@F

オンラインでお試しください!

としてコマンドラインのワンライナー としてperl -asE 'say/^$b(.*)/ for@F' -- -b=frac -、または最後の代わりにファイル名を指定して実行できます-
または、スクリプトファイルから言いますperl -as -M5.010 script.pl -b=frac -(これを示すTIOリンクの@Brad Gilbert b2gillsに感謝します)。

コード自体は18バイトです。コードで-b=指定さ$bれた変数に値(プレフィックス入力)を割り当てるオプションに3バイトを追加しました。これは、通常の「フラグはカウントされません」コンセンサスの例外のように感じました。

-a各入力行をスペースで分割し、結果を配列に入れ@Fます。-sは、コマンドラインに名前を付けることにより、コマンドライン引数を変数として割り当てる簡単な方法です。ここで、引数はです-b=frac。これは、接頭辞「frac」を変数に入れます$b

/^$b(.*)/- $b文字列の先頭の値と一致します。.*単語の終わりまで、その後に続くものは何でも、周囲のパラセテがこの値をキャプチャします。キャプチャされた値は自動的に返され、によって印刷されsayます。スペースで区切られた単語を繰り返し処理for @Fすることは、最初または最後のスペースをチェックする必要がないことを意味します。



1

Perl 6、30バイト

{$^t.comb: /[^|' ']$^p <(\S+/}

試して

拡張:

{  # bare block lambda with placeholder params $p, $t

  $^t.comb:    # find all the substrings that match the following
  /
    [ ^ | ' ' ] # beginning of string or space
    $^p        # match the prefix
    <(         # don't include anything before this
    \S+        # one or more non-space characters (suffix)
  /
}


「p」と「<」の間に余分なスペースがあるようです。
スンダ-復活モニカ

間の空間@sundar p<(それ以外の場合のように見ることができるように必要である$v<…>ため、短いです$v{qw '…'}
ブラッドギルバートb2gills

1
少なくともこの場合、それなしでも動作するようです。
スンダ

1
@sundar技術的には警告するだけですが、警告しないコードと1バイトしか異なる場合に警告するコードを書くのは好きではありません。
ブラッドギルバートb2gills

1

Java 10、94バイト

p->s->{for(var w:s.split(" "))if(w.startsWith(p))System.out.println(w.substring(p.length()));}

こちらからオンラインでお試しください。

ゴルフをしていない:

p -> s -> { // lambda taking prefix and text as Strings in currying syntax
    for(var w:s.split(" ")) // split the String into words (delimited by a space); for each word ...
        if(w.startsWith(p)) //  ... test whether p is a prefix ...
            System.out.println(w.substring(p.length())); // ... if it is, output the suffix
}

1

Small Basic、242バイト

TextWindowオブジェクトへの入力と出力を行わないスクリプト

c=TextWindow.Read()
s=TextWindow.Read()
i=1
While i>0
i=Text.GetIndexOf(s," ")
w=Text.GetSubText(s,1,i)
If Text.StartsWith(w,c)Then
TextWindow.WriteLine(Text.GetSubTextToEnd(w,Text.GetLength(c)+1))
EndIf
s=Text.GetSubTextToEnd(s,i+1)
EndWhile

SmallBasic.comでお試しください! IE / Silverlightが必要



1

Brachylog、12バイト

hṇ₁∋R&t;.cR∧

オンラインでお試しください!

[text, prefix]入力変数を介して入力を受け取り、出力変数を介して各単語生成します。これはもともとスンダーの答えでしたが、「インライン述語と変数を共有する場合は数バイト短くなる可能性があります」と読んでからゴルフを始めました。ジェネレーターの出力がさらに多くのバイトを節約することがわかりました。

    R           R
   ∋            is an element of
h               the first element of
                the input
 ṇ₁             split on spaces,
     &          and the input
      t         's last element
         c      concatenated
       ;        with
        .       the output variable
          R     is R
           ∧    (which is not necessarily equal to the output).

言語のかなり新しい機能を使用して、最初の2つのゴルフダウンの試み。

期待されていたグローバル変数:hA⁰&tṇ₁{∧A⁰;.c?∧}ˢ(18バイト)

apply-to-headメタ述語の場合:ṇ₁ᵗz{tR&h;.cR∧}ˢ(16バイト)

そして、私の元のソリューション:

Brachylog、15バイト

ṇ₁ʰlᵗ↙X⟨∋a₀⟩b↙X

オンラインでお試しください!

同じI / O。これは、本質的に、接頭辞が付いた単語のジェネレータであり、接頭辞ṇ₁ʰ⟨∋a₀⟩を削除するように修正されています。

                   The input variable
  ʰ                with its first element replaced with itself
ṇ₁                 split on spaces
    ᵗ              has a last element
   l               the length of which
     ↙X            is X,
       ⟨   ⟩       and the output from the sandwich
       ⟨∋  ⟩       is an element of the first element of the modified input
       ⟨ a₀⟩       and has the last element of the input as a prefix.
                   The output variable
       ⟨   ⟩       is the output from the sandwich
            b      with a number of characters removed from the beginning
             ↙X    equal to X.

同じバイト数の非常に異なる述語:

Brachylog、15バイト

hṇ₁∋~c₂Xh~t?∧Xt

オンラインでお試しください!

同じI / O。

   ∋               An element of
h                  the first element of
                   the input variable
 ṇ₁                split on spaces
    ~c             can be un-concatenated
      ₂            into a list of two strings
       X           which we'll call X.
        h          Its first element
         ~t        is the last element of
           ?       the input variable,
            ∧      and
             Xt    its last element is
                   the output variable.


0

Pyth21 20 18 17 16バイト

AQVcH)IqxNG0:NG"

オンラインでお試しください!

-1 暗黙的に設定するため、V代わりに使用するFNVN

-2文字列スライスオプションについてさらに詳しく読んだ後

-1を使用xして、インデックス0の部分文字列の存在を確認します

-1文字列の末尾を取得するために「」で置換を使用

これには本格的なゴルフが使用できると確信していますが、Pythの初心者としては、それを機能させるだけでボーナスが得られました。

どのように機能しますか?

assign('Q',eval_input())
assign('[G,H]',Q)
for N in num_to_range(chop(H)):
    if equal(index(N,G),0):
        imp_print(at_slice(N,G,""))

0

Excel VBA、86バイト

入力を接頭辞として入力し[A1]、値を入力[B1]してコンソールに出力します。

For each w in Split([B1]):?IIf(Left(w,[Len(A1)])=[A1],Mid(w,[Len(A1)+1])+" ","");:Next
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.