Scala'da golf oynamak için ipuçları


24

Scala'da golf oynamak için hangi genel ipuçlarınız var? Genel olarak golf problemlerini kodlamak için uygulanabilecek fikirleri arıyorum (en azından Scala'ya özgüdür) (örneğin, "yorumları kaldır" bir cevap değildir). Lütfen cevap başına bir ipucu gönderin.

(Bu, utanmaz bir kopyası ... Python'da)

Yanıtlar:


5

feragatname: bu cevapların bölümleri burada bulunan diğer cevapların genelleştirmeleridir.

Argüman türlerini belirtmeden lambda kullan

Bunun gibi bir şey göndermesine izin verilir: a=>a.sizebunun yerine (a:String)=>a.size.

Tanımlayıcı olarak ascii sembollerini kullanın.

Bunlar arasında !%&/?+*~'-^<>|. Harf olmadıkları için, harflerin yanındayken ayrıştırılırlar.

Örnekler:

a=>b       //ok
%=>%        //error, parsed as one token
% => %      //ok
val% =3     //ok
&contains+  //ok
if(x)&else* //ok

Set yerine Set kullanın

if (Seq(1,2,3,'A')contains x)... //wrong
if (Set(1,2,3,'A')(x))...         //right

Bu mümkün çünkü Set[A] extends (A => Boolean).

İki bağımsız değişkene ihtiyacınız olduğunda curried işlevi kullanın.

(a,b)=>... //wrong
a=>b=>...  //right

_Mümkünse -syntax kullanın

Bunun için kurallar biraz belirsizdir, bazen en kısa yolu bulmak için biraz oynamalısınız.

a=>a.map(b=>b.size)) //wrong
a=>a.map(_.size)     //better
_.map(_.size)        //right

Kısmi uygulama kullan

a=>a+1 //wrong
_+1    //better, see above
1+     //right; this treats the method + of 1 as a function

Yerine ""+kullanıntoString

a=>a.toString //wrong
a=>a+""       //right

Dizileri dizi olarak kullanma

"" acula türünü umursamıyorsanız, bazen boş bir dizi oluşturmanın en kısa yoludur.

Numaraları dizgelere ve dizgelere dönüştürmek için BigInt kullanın.

Bir sayıyı 10 tabanından başka bir tabandaki dizgeye dönüştürmenin en kısa yolu BigInt toString(base: Int)yöntemidir.

Integer.toString(n,b) //wrong
BigInt(n)toString b   //right

Bir dizeyi sayıya dönüştürmek istiyorsanız, BigInt.apply(s: String, base: Int)

Integer.parseInt(n,b) //wrong
BigInt(n,b)           //right

Bunun çoğu zaman bir sayı gibi kullanılabilen, ancak bir dizi için indeks olarak kullanılamayan bir BigInt döndürdüğünü unutmayın.

Dizileri oluşturmak için Sıra kullanın.

a::b::Nil   //wrong
List(...)   //also wrong
Vector(...) //even more wrong
Seq(...)    //right
Array(...)  //also wrong, except if you need a mutable sequence

Karakter dizileri için Strings kullanın:

Seq('a','z') //wrong
"az"         //right

Sonsuz diziler için Stream kullanın

Bazı zorluklar sonsuz bir dizinin n. Elemanını ister. Akış bunun için mükemmel bir aday. Unutmayın Stream[A] extends (Int => A), akış bir dizinden o dizindeki öğeye kadar olan bir işlevdir.

Stream.iterate(start)(x=>calculateNextElement(x))

Wordy meslektaşları yerine sembolik operatörler kullanın.

:\ve :/yerine foldRightvefoldLeft

a.foldLeft(z)(f) //wrong
(z/:a)(f)        //right
a.foldRight(z)(f) //wrong
(a:\z)(f)         //right

hashCode -> ##

throw new Error() -> ???

Kullanım &ve |yerine &&ve||

Booleans için aynı şekilde çalışırlar, ancak her iki operand'ı da her zaman değerlendireceklerdir.

İşlev olarak takma uzun yöntem

def r(x:Double)=math.sqrt(x) //wrong
var r=math.sqrt _            //right; r is of type (Double=>Double)

Standart kütüphanedeki fonksiyonları bilir

Bu özellikle koleksiyon yöntemlerine uygulanır.

Çok faydalı yöntemler:

map
flatMap
filter
:/ and :\ (folds)
scanLeft and scanRight
sliding
grouped (only for iterators)
inits
headOption
drop and take
collect
find
zip
zipWithIndex3
distinct and/or toSet
startsWith

11

Şeyler söyleyip en kısa yolu ile Seq.fill.

1 to 10 map(_=>println("hi!")) // Wrong!
for(i<-1 to 10)println("hi!") // Wrong!
Seq.fill(10)(println("hi!")) // Right!

10

şüpheli tanımlayıcı:

Kullanabilirsiniz ? tanımlayıcı olarak:

val l=List(1,2,3)
val? =List(1,2,3)

Burada size hiçbir şey kazandırmaz, çünkü eşit işarete yapıştıramazsınız:

val ?=List(1,2,3) // illegal

Ancak daha sonra, bir sınırlayıcıya ihtiyacınız olmadığından, genellikle bir karakter kaydeder:

print(?size)  // l.size needs a dot
def a(? :Int*)=(?,?tail).zipped.map(_-_)

Bununla birlikte, kullanımı genellikle zordur:

       print(?size)
3
       print(?size-5)
<console>:12: error: Int does not take parameters
       print(?size-5)
              ^

9

Koleksiyonları

Rasgele bir koleksiyon için ilk tercih genellikle Liste'dir . Çoğu durumda , bir karakter instantan kaydeder Seq ile değiştirebilirsiniz . :)

Yerine

val l=List(1,2,3)
val s=Seq(1,2,3)

ve s.head ve s.tail her zamanki kodda daha şık olsa da s(0), yine bir karakterden daha kısa s.head.

Bazı durumlarda daha da kısa - gerekli işlevselliğe bağlı olarak bir demet:

val s=Seq(1,2,3)
val t=(1,2,3)

hemen 3 karakter kaydetmek ve erişmek için:

s(0)
t._1

doğrudan indeks erişimi için aynıdır. Ancak ayrıntılı kavramlar için, tekiller başarısız:

scala> s.map(_*2)
res55: Seq[Int] = List(2, 4, 6)

scala> t.map(_*2)
<console>:9: error: value map is not a member of (Int, Int, Int)
       t.map(_*2)
         ^

güncelleştirme

def foo(s:Seq[Int])
def foo(s:Int*)

Parametre bildiriminde, Int * Seq [Int] 'in üzerine 4 karakter kaydeder. Eşdeğer değildir, ancak bazen, Int * yapar.


8

Genellikle mapyerine kullanabilirsiniz foreach:

List("a","b","c") foreach println

ile değiştirilebilir

List("a","b","c") map println

Tek fark, kullanırken hiçbir zaman ilgilenmediğiniz iade türü ( Unitvs List[Unit]) foreach.


7

kısa Tipleri tanımlayın:

Bir türün birden fazla bildirimi varsa,

def f(a:String,b:String,c:String) 

bir tür diğer adı tanımlamak ve bunun yerine kullanmak daha kısadır:

type S=String;def f(a:S,b:S,c:S)

Orjinal uzunluk 3 * 6 = 18 Değiştirme kodu 8 (S = tipi) + 6 + 3 * 1 (= yeni uzunluk) = 17

eğer (n * uzunluk <8 + uzunluk + n), o zaman bir avantajdır.

Bir fabrika aracılığıyla başlatılan sınıflar için, o nesneyi işaret edecek daha kısa bir değişken adı ayarlayabiliriz. Yerine:

val a=Array(Array(1,2),Array(3,4))

yazabiliriz

val A=Array;val a=A(A(1,2),A(3,4))

Bu #define, örneğin C ++ için de geçerlidir , ancak bunun güzel defve valdaha kısa olduğunu kabul ediyorum .
Matthew

Hm. defbir yöntemi tanımlayan anahtar kelimedir ve c ++ için basit bir çeviri val'const' dır ve bir bildirimdir, ancak tür genellikle çıkar. Kısalma, type=hangisinin daha yakın olduğu ilk durumda typedef, değil mi? İkinci örnek benden değil ve benim için yeni. Dikkat etmeliyim, nerede kullanacağım.
kullanıcı bilinmeyen

typedef long long ll;aynıdır #define ll long long, bu nedenle ikincisi 1 ile kısalır typedef. valÖrneğe tekrar bakarken kesinlikle yanlış anladım. Scala'ya özgü daha az görünüyor. x = thingWithAReallyLongComplicatedNameForNoReasonoldukça genel bir stratejidir: P
Matthew

Bir örneğini zaman @userunknown Listveya Arraysözdizimi ile vb val x = List(1,2,3)sadece aradığınız applyüzerine yöntemini Listnesne. (Bu nesne oluşturma tekniği, bir yapıcıyı kullanmanın aksine, "fabrika yöntemi" olarak bilinir new.) Yukarıda, yalnızca değişken adıyla aynı singleton nesnesine işaret eden yeni bir değişken yapıyoruz Array. Aynı şey olduğundan, dahil tüm yöntemler applymevcuttur.
Luigi Plinge 12:11

7

.Karakter ihtiyacını ortadan kaldırmak için infix sözdizimini kullanın . Bitişik öğeler hem alfasayısal ya da her ikisi de işleç karakterlerinde ( buraya bakın ) ve ayrılmış karakterlerle (parantez, virgül vb.) Ayrılmadıkça boşluklara ihtiyacınız yoktur .

Örneğin

List(1,2,3,4).filter(_ % 2 == 0) // change to:
List(1,2,3,4)filter(_%2==0)

7

trueVe falsedeğişmezleri olarak yazma için kısadır 2>1gerçek ve 1>2yanlışın


7

Başlatma için aynı işlevi iki kez arayın:

val n,k=readInt

(Başka bir yerde gördüm, ama şimdi bulamıyorum).


6

İsimleri uzunsa ve birden çok kez kullanılıyorsa, Yeniden Adlandırma Yöntemleri - gerçek dünya örneği:

 x.replaceAll(y,z)

 type S=String; def r(x:S,y:S,z:S)=x.replaceAll(y,z)

'S = String'i farklı yerlere kaydetme olasılığına bağlı olarak, en az 3 kez değiştirirseniz, bu yalnızca ekonomik olacaktır.


3

Bir tuple kullanarak aynı anda birkaç değişkeni başlat:

var(a,b,c)=("One","Two","Three") //32 characters

vs.

var a="One";var b="Two";var c="Three" //37 characters

0

İşlev tanımları için kullanmak yerine de kullanabilirsiniz =>.


1
Merhaba ve PPCG'ye hoş geldiniz. Çoğu zaman, cevaplar karakterlerden ziyade bayt olarak sayılır, ipucunuzun sadece sınırlı bir kapsamı vardır. Bunu ele alır ve ayrıca karakter sayımına dayalı kod golf mücadelelerinde Kısaltma işlevi tanımları gibi bir ipucu eklerdim .
Jonathan Frech
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.