GolfScript'te golf oynamak için ipuçları


35

Bu yazı henüz yok mu?

Tabii ki, GolfScript golf oynamak için yapılır , bu yüzden herhangi bir özel ipucuna gerek olmadığını düşünebilirsiniz. Ancak GolfScript'in özelliklerinden tam anlamıyla faydalanmak için, bazı açık olmayan püf noktaları öğrenmeniz gerekir. Bu yazı, bu tür yararlı ipuçları ve püf noktaları toplamak içindir.

Başlamak için, burada resmi GolfScript referans sayfaları. İlk önce kendinizi gerçekten tanımanız gerekir:

Özellikle, sayfaları bu sırayla okumanızı öneririm - hızlı başvuru, yerleşik yapılara zaten yeterince aşina oluncaya kadar çok az kullanışlıdır ve öğretici, diğer sayfalarda açıklanmayan bazı önemli ayrıntıları içermektedir. .


Ps. İlham ve kişisel ilgi uğruna, işte size güzel cevapları görmek istediğim bazı sorular :

  • GolfScript'te sınırlı harf çevirisi nasıl yapılır? {FROM?TO=}%eserler eğer emin tüm girişler bulunur sen edilebilir FROM(veya hepsini son elemana işaretlendiğini sakıncası TO), ama değişmeden bağlanılmayan değerlerini bırakmak için gördüğüm tüm yolları az çok klugey olmuştur.

  • Bir dize ASCII kodları dizisine dönüştürmek ve geri nasıl? Hangi işlemler bunu yan etki olarak yapar? Dizedeki karakterleri yığına dökmenin en iyi yolu nedir ( ~dizilerde olduğu gibi )?


Başka bir soru: dönüştürmek için güzel bir yol vardır ... xiçine ... [x]? Görebildiğim en iyi şey [.;].
Peter Taylor

@Peter: Eğer xbir sayı ise, []+çalışır ve bir karakter daha kısadır. Ve elbette, eğer xyığındaki tek şey varsa , o ]zaman yapacağız.
Ilmari Karonen

Yapmanın en iyi yollarını sormak isterim: min, maks ve mutlak değer. Tüm çözümlerim olması gerekenden daha fazla karakter alıyor gibi görünüyor.
Claudiu

Bir diziyi verilen bir dizinde değiştirmenin en iyi yolu nedir?
user1502040

@ user1502040: Aşağıda cevaplandı . (Herkes daha iyi bir yol biliyorsa, lütfen paylaşın!)
Ilmari Karonen

Yanıtlar:


29

Rasyonel / Şamandıra / Kompleks

GolfScript'in yalnızca inanmaya başladığım tam sayılara sahip olduğunu birçok kez okudum. Eh, doğru değil.

2-1? # Raise 2 to the power of -1. Result: 0.5
4-1? # Raise 4 to the power of -1. Result: 0.25
+    # Add. Result: 0.75

Çıktı

3/4

Standart GolfScript tercümanı ile ve

0.75

üzerinde Web GolfScript .

Benzer saldırılar, Rasyonel, Float ve hatta Karmaşık dökümlere izin verir:

{-2.?./*}:rational
{2.-1??./*}:float
{-2.-1??./*}:complex

9
OMGWTFHAX o_O !!!
Ilmari Karonen

3
WAT! Eminim bu tercüman bir hata, ama vay
Doorknob

3
Çizgi En son tercüman 82: Gint.new(@val**b.val). Görünüşe göre Gint
kurucuda

10

Bir numarayı olumsuzlamak

GolfScript'in sahip olmadığı tek şey yerleşik bir olumsuzlama operatörüdür. Gibi bariz yolları, onun negatife yığın bir numara dönüştürme -1*veya 0\-üç karakter gerekir. Ancak, bunu ikiye yapmanın bir yolu var:

~)

Bu işe yarar çünkü GolfScript ikinin tamamlayıcı aritmetiğini kullanır , böylece ~ x eşittir - x --1 .

Tabii ki, değişken (~de çalışır; aralarında seçim yapmak genellikle bir zevk meselesidir.


9

Diziyi karıştırma

Bir diziyi GolfScript'te karıştırmanın en kolay yolu, onu rasgele bir sıralama anahtarıyla sıralamaktır. Yalnızca birkaç değeri kabaca karıştırmanız gerekirse, aşağıdaki kod uygulanacaktır:

{;9rand}$

Kısa listeler için bile, bunun çok iyi bir karıştırma vermeyeceğini unutmayın. Doğum günü paradoksundan dolayı , makul derecede homojen bir karışıklık elde etmek için, tartışmanın randkarıştırılmakta olan listenin uzunluğunun karesinden önemli ölçüde daha büyük olması gerekir.

Bu nedenle 9yukarıdakilerin değiştirilmesi, 99on öğeye kadar olan listeler için oldukça iyi sonuçlar verir, ancak daha uzun listeler için gözle görülür önyargı sergiler.

9 9 = 387,420,489 olası değerleri kullanan aşağıdaki kod, yaklaşık 1000 öğeye kadar faydalı olabilir (ve yaklaşık 20.000'e kadar kabul edilebilir):

{;9.?rand}$

Gerçekten uzun listeler için 99 99 ≈ 3.7 × 10 197 değerlerine bir 9 daha ekleyin :

{;99.?rand}$

Test yapmak:

İlk öğenin, yukarıda gösterilen farklı değişkenler kullanılarak karıştırılmış, 10.000 denemeden örneklenen 10 öğe listesinde dağılımı:

  • Çıktısı 10,{;9rand}$0=çok açık bir önyargı gösterir 0ve ilk sıraya çıkması muhtemel üç kezden fazla olur 1:

    0 16537 #######################################################
    1 5444  ##################
    2 7510  #########################
    3 8840  #############################
    4 9124  ##############################
    5 12875 ##########################################
    6 9534  ###############################
    7 8203  ###########################
    8 7300  ########################
    9 14633 ################################################
    
  • İle 10,{;99rand}$0=, önyargı çoğu öldü, ama farkedilir bir miktar hala kalır:

    0 10441 ##################################
    1 9670  ################################
    2 9773  ################################
    3 9873  ################################
    4 10134 #################################
    5 10352 ##################################
    6 10076 #################################
    7 9757  ################################
    8 9653  ################################
    9 10271 ##################################
    
  • İle 10,{;9.?rand}$0=, çıktı gerçekten rastgele bir örnekten ayırt edilemez:

    0 9907  #################################
    1 9962  #################################
    2 10141 #################################
    3 10192 #################################
    4 9965  #################################
    5 9971  #################################
    6 9957  #################################
    7 9984  #################################
    8 9927  #################################
    9 9994  #################################
    

Ps. İçin gerçekten sayısal dizi veya dizeleri kötü karma, aşağıdaki kod bazen kabul edilebilir:

{rand}$

Genelde gülünç bir şekilde önyargılı olacaktır, ancak girdi dizisinin tüm elemanları (veya dizedeki tüm karakter kodları) bir taneden büyük olduğu sürece, dizinin herhangi bir permütasyon üretme olasılığı sıfırdır, bazen tatmin edici olabilir. kötü yazılmış meydan okuma gereksinimleri.


3
Bir keresinde, kardeşim bana anlattıktan sonra, doğum günü paradoksu için matematiği kuşkuyla yaptığımı hatırlıyorum, o haklıydı: (
ajax333221

8

Belirli bir alt soruyu ele almak için:

Bir dize ASCII kodları dizisine dönüştürmek ve geri nasıl? Hangi işlemler bunu yan etki olarak yapar? Dizedeki karakterleri yığına dökmenin en iyi yolu nedir (diziler için ~ yapar)?

Sorunu anlamayanlar için, GolfScript'in yazım sistemi, sipariş tamsayı, dizi, string, blok türlerine öncelik verir. Bu, bir dizeye uygulanan sıradan dizi işlemlerinin hemen hemen her zaman bir dize verdiği anlamına gelir. Örneğin

'ABC123'{)}%

'BCD234'yığında bırakacağım .

Sonuç olarak, bir dizgiyi bir ASCII kod dizisine dönüştürmenin en iyi yolu karakterleri yığına dökmek ve daha sonra bunları bir diziye toplamaktır.

Dizedeki karakterleri yığına dökmenin en iyi yolu nedir? {}/

Bir dizgiyi bir dizi ASCII koduna dönüştürmenin en iyi yolu nedir? [{}/](Her zamanki ihtar ile yığında başka bir şey yoksa atlayabilirsiniz [)

Bir dizi ASCII kodunu dizgeye dönüştürmenin en iyi yolu nedir? ''+(Örneğin, çok Not Bu da, bir dizi düzleştirir bu [65 [66 67] [[[49] 50] 51]]''+verir 'ABC123')


Tek bir ASCII kodunu dizgeye dönüştürmenin en iyi yolu nedir? []+''+? (oldukça uzun görünüyor)
Justin

@ Quincunx, oldukça uzun, ama daha iyi bir yol bilmiyorum. Yapılacak şey, ASCII kodunun nereden geldiğine bakmak ve bir diziye zaten ulaşıp ulaşamayacağınızı görmek olabilir.
Peter Taylor

6

Programınız gizlice bozulursa değişkenlerinizi kontrol edin

Sadece bir süre !değişken olarak kullanılan doğru bir programda hata ayıklamakla harcadım (tekrar kullanmayacağım gerekçesiyle). Ne yazık ki yaptığımız kullanımını ifve uygulanmasının çıkıyor ifaramalar !takip etmek hangi dalı karar vermek.


6

Yığının üst öğesinin bir diziye sarılması

Dönüştürmek için güzel bir yol var mı ... xiçine ... [x]?

Genel olarak, en iyi seçenek 4 karakter gibi gözüküyor. Bununla birlikte, bazı özel durumlarda bunu azaltmak mümkündür.

1 karakter

]xYığın üzerindeki tek şey olan özel durumda çalışır .

3 karakter

[]+xtamsayı olan özel durumda çalışır .

.,/xBir truthy dizi veya dize olan özel durumda çalışır . Örneğin "AB".,/verir ["AB"]; 3,.,/verir [[0 1 2]]. Ancak, "".,/ve [].,/her ikisi de vermek [].

4 karakter

[.;] koşulsuz çalışır.


6

Bir diziyi verilen bir dizinde değiştirmenin en iyi yolu nedir? - kullanıcı1502040

Bu iyi bir soru. GolfScript'te bir dizi öğesine bir değer atamanın doğrudan bir yolu yoktur, bu nedenle, bir şekilde veya diğerinde, tüm diziyi yeniden oluşturmanız gerekir.

Bir dizideki xdizine yeni bir değer eklemeyi bildiğim en kısa yol i, diziyi verilen dizinde bölmek ve xtekrar birleştirmeden önce ilk yarıya eklemektir:

  • .i<[x]+\i>+(11 karakter) - değeri x(0 temelli) dizindeki diziye ekleyini

To yerine endeksinde değer iile xbiz sadece bir öğe tarafından dizinin ikinci yarısını kısaltmak gerekir:

  • .i<[x]+\i)>+(12 karakter) - (0 temelli) dizindeki öğeyi ideğerle değiştirx

Alternatif olarak, ilk yarıyı kısaltmak yerine etkili bir şekilde aynı şeyi yapar, ancak bazen tercih edilen 1 tabanlı endekslemeyle:

  • .i(<[x]+\i>+(12 karakter) - (1 temelli) dizindeki öğeyi ideğerle değiştirx

Yukarıdaki tüm örneklerde, eğer xbir sayı ise, etrafındaki köşeli parantezler iki karakter kaydetmek için çıkarılabilir, çünkü +yine de bir diziye otomatik olarak zorlanacaktır :

  • .i<x+\i>+(9 karakter) - sayıyı x(0 temelli) dizindeki diziye ekleyini
  • .i<x+\i)>+(10 karakter) - (0 temelli) dizindeki öğeyi isayı ile değiştirx
  • .i(<x+\i>+(10 karakter) - (1 tabanlı) dizindeki öğeyi isayı ile değiştirx

Eğer ya xda "array" girişi (ya da her ikisi de) aslında karakter dizisi ise parantezler de çıkarılabilir , bu durumda sonuç dizeye zorlanacaktır (normal dizi → karakter dizisi dönüştürme kuralları kullanılarak).


Ps. Özel bir durum olarak, dizinin i2 × ieleman arasında olduğunu biliyorsak x, (0-tabanlı) dizininde (6 karakter) iile yeni bir eleman ekleyebiliriz i/[x]*. Bunun gerçekte yaptığı şey, diziyi iöğelere kadar olan öbeklere bölmek ve xher öbek arasına eklemek . Bu durumda, xbir sayı olsa bile braketlerin gerekli olduğunu unutmayın .


Pps. Alternatif bir yaklaşım, dinamik olarak adlandırılmış değişkenleri kullanmaktır. Örneğin,

 'foo' 42 ':x'\+~

değerini atar 'foo'değişkene x42iken,

 42 'x'\+~

onu alacağım.

Bunu xönek ekleyerek ve yalnızca sayısal hazırlayıcılara doğrudan atayarak daha da iyileştirebilirsiniz - bu, GolfScript'te tamamen yasaldır ve atama kodundan bir karakter kaydetmenize ve alma kodunu yalnızca `~(veya hiçbir şey, Dizin sabittir!). Tabii ki, aşağı tarafı, sayısal bir değişmeze atamak, bu değişmezin değerini kodunuzda başka bir yerde geçersiz kılar. Yine de, çoğu zaman, sayı değişmezlerinin kullanımından kaçınılabilir (veya en azından programın başlangıcına, herhangi biri yeniden atanmadan önce), bu durumda bu hile tamamen iyidir.


3
Tamamen konu dışı: 10k için tebrikler! :-D
Doorknob

1
Dizinin yinelenen değerleri olmadığını biliyorsanız, i9 bayt için dizindeki bir değeri değiştirebilirsiniz :.[i=]/[x]*
Martin Ender

5

Son çıktı manipülasyonu

Varsayılan olarak, programınız sona erdiğinde, GolfScript yorumlayıcısı yığınınızdaki her şeyi ve son olarak da programın sonuyla bitmiş gibi son bir yeni satırı çıkarır:

]puts

Belgelerin doğrudan bahsetmediği, tercümanın kelimenin tam anlamıylaputs bu çıktıyı üretmek için yerleşik olarak çağırdığı ve bu dahili olarak kelimenin tam anlamıyla tanımlandığı:

{print n print}:puts;

Böylece, bastırmak veya yeniden tanımlayarak nihai çıktısı yapabilen puts, print ve / veya n(veya  sen duygu gerçekten bükülmüş ise). İşte bazı örnekler:

Son satırın gösterilmesi:

'':n;

(Tabi ki ;istifte fazladan boş bir ipin sakıncası yoksa dışarıda bırakabilirsiniz .)

Son çıktıyı tamamen bastır:

:puts

Bu puts, yığında ne olursa olsun üzerine yazar . Bu yürütmek istemediğiniz bir şey olursa, örneğin kullanabilirsiniz 0:puts;. Bunun da p(yani olarak tanımlanmıştır {`puts}:p;) bastırdığını unutmayın , ancak isterseniz printçıktı için hala kullanabilirsiniz .


Ve nothingdemek istediğin \n?
Hesap MakinesiFeline

Sondaki yeni çizgiye aldırış etmiyorsanız, ];son çıktıyı bastırmak için de kullanabilirsiniz .
Wastl

5

Yapmanın en iyi yollarını sormak isterim: min, maks ve mutlak değer. Tüm çözümlerim olması gerekenden daha fazla karakter alıyor gibi görünüyor. - Claudiu

en az en çok

Bir dizideki en küçük / en büyük değeri bulmak için, onu sıralamanız ve ilk / son öğeyi almanız yeterlidir:

  • $0= (3 karakter) - bir arry'de minimum eleman
  • $-1= (4 karakter) - bir dizideki maksimum eleman

Dizinin uzunluğunu biliyorsanız ve 10 veya daha az -1öğe ise, son öğenin dizini ile değiştirerek en fazla üç karakterde bulabilirsiniz .

Yığında değerleri varsa, önce onları bir dizide toplayabilirsiniz. Bunun için, zaman zaman faydalı bir hile, [\]yığının en üst iki öğesini bir diziye [@]toplarken ilk üçü toplar. Böylece, biz alırız:

  • [\]$0= (6 karakter) - yığında en az iki değer
  • [@]$0= (6 karakter) - yığında en az üç değer
  • [\]$1= (6 karakter) - yığında maksimum iki değer
  • [@]$2= (6 karakter) - yığında en çok üç değer

Aynı numara, ara sıra faydalı olabilecek üç değerin medyanını bulmak için de kullanılabilir :

  • [@]$1= (6 karakter) - yığında üç değerin medyanı

Orijinal değerleri yığında bırakırken, iki değerin min / maks'unu bulmak için potansiyel olarak yararlı bir püf nokta :

  • .2$>$ (5 karakter) - orijinal değerleri el değmeden bırakırken yığın üzerinde minimum iki değer bulun
  • .2$<$ (5 karakter) - orijinal değerleri el değmeden bırakırken yığın üzerinde maksimum iki değer bulun

Çalışma şekli .2$, istif üzerindeki en üstteki iki öğeyi ters sırada (yani a ba b b a) klonlar , </ >karşılaştırır ve 0 veya 1 döndürür ve skaler $, karşılaştırmanın sonucuna bağlı olarak iki giriş değerinden birini kopyalar.


Yığında iki negatif olmayan tamsayı varsa, ,\,&,minimumlarını bulmak için ,\,|,(5 karakter) ve maksimumlarını bulmak için (5 karakter) kullanabilirsiniz. Bu numara, aralıkların üzerinde sırasıyla set kesişimi ve birliğini kullanır. ,Her argümana ayrı ayrı değiş tokuş etmek gerekmiyorsa, başka bir karakter kaydedebilirsiniz . Bu yöntem, her bir argüman için bir aralık hesapladığından, daha büyük sayılar için çok verimli değildir, ancak daha küçük girişler için çok yararlı olabilir.

Yığında negatif olmayan iki tam sayıyı bulmanın daha da kısa bir yolu ,<,(3 karakter). Ne yazık ki, bu numara maksimum bulmaya çalışmıyor.


mutlak değer

GolfScript dahili mutlak değeri operatörü olan abs(3 karakter). Bu tercih ettiğimden daha fazla iki karakter olsa da, genel olarak yenmek zor.

Bazı durumlarda (örneğin mutlak değere göre sıralama için) bir sayının karesini mutlak değer için uygun bir alternatif olarak bulabilirsiniz; Bu, ya 2?da , iki karakterle hesaplanabilir .*. Böylece, biz alırız:

  • {.*}$0= (7 karakter) - dizideki mutlak değere göre minimum öğe
  • {.*}$-1= (8 karakter) - dizideki mutlak değere göre maksimum öğe

Benzer şekilde, örneğin bir sayının mutlak değerinin 3 ile abs 3<(6 karakter, boşluk dahil) 3'ten küçük olup olmadığını test etmek yerine, .*9<(9 karakter, boşluk gerekmeden) karesinin 9'dan küçük olup olmadığını test edebilirsiniz .


Yığında iki negatif olmayan tamsayı varsa, ,\,&,minimumlarını bulmak için ,\,|,(5 karakter) ve maksimumlarını bulmak için (5 karakter) kullanabilirsiniz. Bu numara, aralıkların üzerinde sırasıyla set kesişimi ve birliğini kullanır. ,Her argümana ayrı ayrı değiş tokuş etmek gerekmiyorsa, başka bir karakter kaydedebilirsiniz . Bu yöntem, her bir argüman için bir aralık hesapladığından, daha büyük sayılar için çok verimli değildir, ancak daha küçük girişler için çok yararlı olabilir.
Kirarin 14

@KirarinSnow: Teşekkürler! Cevaba ekledim.
Ilmari Karonen

4

Bir diziden kopyaları kaldırma

Set operatörleri |(sendika), &(kesişme) ve ^(simetrik fark), çoklu dizi elemanlarını bire böler. Bu nedenle, bir diziden yinelenen öğeleri kaldırmanın en basit yolu, onunla birleşme veya kesişme işleminin gerçekleştirilmesidir:

.|

veya:

.&

Bu işleçler dizeleri karakter dizisi olarak değerlendirir, bu nedenle dizeleri yinelenen karakterleri kaldırmak için de kullanılabilirler.


4

Sınırlı harf çevirisi

Belirli bir alt soruyu ele almak için: bir dize verildiğinde, bunu gerçekleştirmenin en iyi yolu trnedir? Örneğintr/ABC/abc/

Dizedeki tüm karakterler etkilenecekse, bu oldukça kolaydır: {'ABC'?'abc'=}%(ek yük: 9 karakter).

Ancak, bazı karakterlerin harfleri çevrilmemişse ve 'ABC'?verirse bu kırılma olur -1.

Harf çevirisi döngüsel değilse, dize yarıkları ve eklemleri ile bir seferde bir değişiklik yapılabilir: 'AaBbCc'1/2/{~@@/\*}/(ek yük: 15 karakter). Bu iyileştirilebilir olabilir, ancak şu anda daha iyi olan ve döngüsel çeviriler için çalışan alternatif bir yaklaşım var.

Şu anda, en kısa genel çözümler 14 karakterden oluşan bir ek yüke sahip:

  • Bir yaklaşım, bir kaçış karakterini içerir: burada bir hazır bilgi boş bayt anlamına gelir. (Elbette, bu yöntem tamamen genel değildir : başka bir karakteri boş bir bayta eşleyemez.){.'ABC'?'abc0'=\or}%0

  • Alternatif olarak, {.'ABC'?'abc'@),+=}%aynı ek yükü vardır, ancak yalnızca yazdırılabilir ASCII karakterlerini kullanır. Yeni @),+dizgenin her zaman giriş karakteriyle bitmesini sağlamak için kıvrımlı (ancak en kısa yoldan) yoludur.


Son yaklaşımı kullanarak, girdi dizgisi 'ABCDEF'için sonucu alıyorum 'abc000', ancak doğru sonuç olacak 'abcDEF'. Bir şey mi eksik?
Cristian Lupascu

1
@ w0lf, bu 0 kalın, çünkü daha önce belirtilen kaçış karakteri - yani bayt 0
Peter Taylor

4

Karakter dizisine bir dize çevirme

Bunu yazarak yapabilirsiniz: 1/ondan sonra.

Örnek: "String"1/diziyi istiflemek için iter ['S''t''r''i''n''g'].

Karakterleri dizginin etrafında hareket ettirmek istediğinizde bu kullanışlıdır.


1
Bunun nasıl kullanışlı olabileceğine dair bir örnek verebilir misiniz? Dizeler zaten diziler gibi davranıyorlar, bu yüzden bu kullanışlı görünmüyor.
Justin

@ Quincunx ascii değerlerini değil karakterlerini ortaya çıkarmak istediğinizde kullanışlıdır
user3700847

Peki bunu ne zaman yapmak istersin?
Justin

5
@Quincunx: Örneğin bir dize döndürme. "abc"1/(+-> "bca", fakat "abc"(+-> bc97.
Dennis,

4

Sayı değişmezlerine atama

Genellikle, 1:xdeğişkeni yazmak ve kullanmak / güncellemek yerine, doğrudan doğrudan xkullanabilir ve güncelleyebilirsiniz 1:

1:^;{^.p.+:^;}5*
{1.p.+:1;}5*       (4 bytes shorter)

Elbette, bu diğer başlangıç ​​değerleri için de işe yarar, ancak bu değer kodunuzda başka bir yerde olursa kırılır.

Değişken adları olarak noktalama işaretleri

Eğer varsa sahip olmadan yapabileceği programların bir sürü - değişkenlerini kullanmak, bu kodun önceden bulunmadığından noktalama işareti kullanmayın çoğu zaman akıllıca da var &, |, ^, veya ?. Bu şekilde, örneğin değişkeninizi itmek &nyerine yazabilir x nve ardından yeni bir satıra basabilirsiniz .


3
Bazı ödevlerin beklenmedik yan etkileri olabilir. Özellikle, atama !o kıracak gibi genellikle kötü bir fikir olduğunu ifve do(aynı zamanda while, until, and, orve xor). Benzer şekilde, oriçin bir takma ad olarak yorumlayıcı tarafından tanımlanan 1$\iftanımlayıp, böylece 1, $ya \da kıracak. Yeniden Tanımlanması `sonları p.
Ilmari Karonen

3

Bir diziyi filtrelemek

Bir diziyi filtrelemenin en genel yolu, dizinin { },her elemanı için kod bloğunu değerlendiren ve elde edilen değerin doğru olduğu elemanları seçen (yani grepPerl'deki gibi ) seçen kullanmaktır .

Ancak, dizi çıkarma işlecini -kullanmak genellikle daha kısadır. Bu operatör iki dizi alır ve ikinci dizide meydana gelen her elemanı ilkinden kaldırır. Bu etmez olmayan ilk dizi veya çökme çiftleri öğelerin sırasını değiştirmek. Çöken olmayan bir dizi kesişim operatörünü elde etmek için çıkarma işlemini iki kez uygulamak yararlı bir püf noktasıdır:

  • a b -: Dizide bulunan herhangi öğeleri kaldırmak bdizidena
  • a. b --: Öğelerini ortadan kaldırmak olup dizide bulunan bdizidena

Özellikle, bu, bir elementin bir dizide kaç kez oluştuğunu saymak için kullanılabilir :

  • a.[c]--,: elemanın cdizide kaç kez meydana geldiğini sayara

Genel olarak, bu yöntem aşağıdakilerden herhangi birinden dolayı optimal değildir:

  • a[c]/,(: elemanın cdizide kaç kez meydana geldiğini sayara
  • a{c=},,: elemanın cdizide kaç kez meydana geldiğini sayara

bir karakter daha kısadır (ve sayının birer birer kapatılması a[c]/,tamamsa, bir karakterden daha fazla tasarruf sağlar). Bununla birlikte, cbir sayı olan ve anormal bir dizi olan (bir dize olmayan) özel durumda c, -işleç argümanlarını aynı türe zorladığından, etrafındaki köşeli parantezler kullanılmayabilir :

  • a.c--,: sayının cdizide kaç kez meydana geldiğini saymak (string! değil)a

(Eğer abir dizge ve c0 ile 9 arasında bir sayı ise a.c--, basamağın c gerçekleştiği sayıyı sayar a.)


Benzer bir numara, bir dizideki en yaygın elemanı bulmak için kullanılabilir :

:a{a\[.]-,}$0=

Yine, eğer girdi bir sayı dizisi ise, dizinin tamamı [.]ihmal edilebilir. Ne yazık ki, bu mu değil olmadan dizeleri için çalışmak [.].


Olayları saymak için (genel durum) a[c]/,(ve a{c=},,bir bayt daha kısa.
Dennis,

@Dennis: Teşekkürler! Bunu da düzenledim.
Ilmari Karonen

3

STDIN'den okuyun

GolfScript stdin'den okuyabilir:

"#{STDIN.read}"

Bu, EOF'ye ulaşılana kadar STDIN'den okumaya devam edecektir. Alternatif:

"#{STDIN.gets}"

veya

"#{STDIN.readline}"

Mevcut diğer şeyler:

getbyte
getc
gets([sep])
gets(limit)
gets(sep, limit)
inspect # perhaps useful for an underhanded contest
isatty
read([length])
readbyte
readchar
readline([sep])
readline(limit)
readline(sep, limit)
readlines([sep])
readlines(limit)
readlines(sep, limit)
readpartial(maxlen [, outbuf])

Bunların her biri için yalnızca bir kez kullanılabilir (ve ayrıca her parametre değişikliği için bir kez, ayrıca bir kez daha boş parantez içinde); Bundan sonra, orijinal değer, yeni bir değer yerine elde edeceğiniz şeydir.


2
{"#{STDIN.readline}"p}2*2 satır okumayan ancak bunun yerine bir kez değerlendirilen bir açıklama eklemek isteyebilirsiniz .
Howard

2
Herhangi ibir tamsayı başlatırsanız , '"#{'i):i';STDIN.gets}"'++~her değerlendirildiğinde farklı bir sonuç verecektir. Geri tepmeler de söylemeye değer olabilir. Eğer Linux varsayalım, örneğin, `head -1`yerine kullanabiliriz STDIN.gets.
Dennis,

@Dennis: stdin'den bir satır okuyan ve yığına iten yeni bir GolfScript operatörü tanımlamanıza"#{var'g','gpush Gstring.new(STDIN.gets)'.cc}"; izin verir . g
Ilmari Karonen

2

Onaltılık girişin kodunu çözme

GolfScript'in altıgen tamsayı değişmezleri yok, bu yüzden ne yazık ki, onaltılık bir girdiyi ayrıştıramazsınız ~. Bunun yerine, kodunuzun onaltılı giriş alması gerekiyorsa, el ile ayrıştırmanız gerekir.

Bir dizeye uygulanan bu 8 karakterlik döngü küçük harfli altıgen haneleri sayısal eşdeğerlerine dönüştürür:

{39%9-}%

Büyük harfli onaltılık basamağı (ayrıca) kabul etmeniz gerekiyorsa, en kolay (ve muhtemelen en kısa) çözüm, 32|toplamda 11 karakter için ilk önce küçük harflerle yazmaktır:

{32|39%9-}%

Çıktının teknik olarak hala bir dize olacağına dikkat edin (ASCII karakterleri 0 - 15'ten oluşur), ancak GolfScript dizi işlevlerinin çoğu da dizeleri kabul eder. Kesinlikle bir diziye ihtiyacınız varsa, her zaman kullanabilirsiniz [{39%9-}/]( [yığın başka bir şey boşsa ilk isteğe bağlı olan).

Yukarıdaki kodun çıktısını bir tamsayıya dönüştürmek için, sadece 16base(6 karakter) kullanabilirsiniz. Bunun yerine bir bayt dizisi istiyorsanız, bulduğum en kısa çözüm, her onaltılık basamağın çiftini 2/{16base}%(11 karakter) çözmek için buldum . Hepsi bir araya getirildiğinde, onaltılık bir dizgiyi bir bayt dizisine dönüştürdüğüm en kısa kod 8 + 11 = 19 karakter:

{39%9-}%2/{16base}%

Bu kodun çıktısı unutmayın olduğunu gerçekten bir dizi değil, bir dize. Gerekirse, sonunda ""+veya başka bir satırsonu sakıncası yoksa, örneğin veya ile birleştirerek onu dizge altına alabilirsiniz n+.


2

Yeni yerleşik operatörleri tanımlama

Standart GolfScript yorumlayıcısı, çift ​​tırnaklı dizgilerde enterpolasyonlu Ruby koduna izin veren nadiren kullanılan bir özelliğe sahiptir.

Bu özelliğin daha yaygın kullanılmamasının nedenlerinden biri , enteresan olarak , enterpolasyonlu kodun derleme zamanında çalıştırılması ve çıktının GolfScript yorumlayıcısı tarafından önbelleğe alınmasıdır, böylece aynı string değişmezi daha sonra her zaman aynı değeri verir. string eval.

Bununla birlikte, bu özelliğin iyi olduğu ortaya çıkan bir şey, Ruby kodunda uygulanan yeni GolfScript operatörlerini tanımlamaktır. Örneğin, standart yerleşik +operatör gibi çalışan yeni bir ikili ekleme işlecini nasıl tanımlayacağınız :

"#{var'add','gpush a+b'.cc2}";

Tanımı kodunuzda nereye koyduğunuz önemli değil; yeni operatör Ruby kodunu içeren çift tırnaklı dize ayrıştırıldığında tanımlanır. addOperatör eserler yukarıda tanımlanan aynen böyle yerleşik +operatör ve tamamen aynı şekilde kullanılabilir:

1 2 add          # evaluates to 3
"foo" "bar" add  # evaluates to "foobar"

Tabii ki, yeni bir ekleme operatörü tanımlamak , yerleşik +operatörü silmek gibi aptalca bir şey yapmadıysanız oldukça işe yaramaz . Ancak, aynı hileyi, Golfscript'in (kolayca) bir diziyi düzgün bir şekilde karıştırmak gibi doğal olarak yapamayacağı şeyleri yapan yeni operatörleri tanımlamak için kullanabilirsiniz:

"#{var'shuf','gpush a.factory(a.val.shuffle)'.cc1}";

10,shuf          # evaluates to 0,1,2,...,9 in random order

veya tüm yığının içeriğini basmak:

"#{var'debug','puts Garray.new($stack).ginspect'.cc}";

4,) ["foo" debug  # prints ["" [0 1 2] 3 "foo"], leaving the stack untouched

veya etkileşimli girdi:

"#{var'gets','gpush Gstring.new(STDIN.gets)'.cc}";

]; { "> " print gets ~ ]p 1 } do   # simple GolfScript REPL

hatta web erişimi:

"#{
  require 'net/http'
  require 'uri'
  var'get','gpush Gstring.new(Net::HTTP.get_response(URI.parse(a.to_s)).body)'.cc1
}";

"http://example.com" get

Tabii ki, ikincisinin bir nevi golfçü (ve daha riskli!) Uygulaması şöyle olacaktır:

"#{var'get','gpush Gstring.new(`curl -s #{a}`)'.cc1}";

Kendisinde özellikle golf sahası olmamakla birlikte, bu, GolfScript'in özelliklerini yerleşik komutların sağlamasının ötesine genişletmenize olanak tanır.


O nasıl çalışır?

Yeni GolfScript operatörlerinin bu şekilde nasıl tanımlandığına dair yetkili referans, elbette, tercüman için kaynak koddur . Yani, işte birkaç hızlı ipucu:

  • nameRuby kodunu çalıştıran yeni bir operatör tanımlamak için şunu codekullanın:

    var'name','code'.cc
  • Kodun içinde, gpopyığından bir değer okumak ve gpushgeri almak için kullanın. Yığına doğrudan dizi yoluyla da erişebilirsiniz $stack. Örneğin , yığının her ikisine ave byığına itmek, yapmaktan $stack<<a<<bdaha golfcüdür gpush a;gpush b.

    • [Dizi başlangıç ​​işaretleyicilerinin pozisyonları dizide saklanır $lb. gpopFonksiyon yığın daralmaları konumları aşağıdaki ise aşağı bu belirteçler ayarlanması ancak manipüle ilgilenir $stack, doğrudan dizi değildir.
  • .ccBir GolfScript operatörü içine dizede Ruby kodu derler dize yöntemi etrafında sadece bir kolaylık sarıcı Gblock.new(). Ayrıca varyantları bulunur .cc1, .cc2ve .cc3bu operatör otomatik yığın kapalı, 1, 2 ya da 3 argüman açılır ve değişkenlere atamak yapmak a, bve c. Argüman türlerini otomatik olarak önceliğe göre sıralaması dışında, bunun .ordergibi çalışan bir yöntem de vardır ..cc2

  • GolfScript yığında tüm değerler (ve! Olmalıdır) tip nesneler Gint, Garray, Gstringya da Gblock. Temelde bulunan yerel tamsayıya veya diziye ihtiyaç duyulduğunda yöntemle erişilebilir .val.

    • Ancak, s Gstring.valdizisini döndüren not Gint! Bir açmak için Gstringbir yerli Ruby dizeye çağrıyı .to_syerine üzerinde (veya dize enterpolasyon gibi otomatik Bunu yapan bir bağlamda kullanın). .to_gsHerhangi bir GS değerini çağırmak onu bir Gstringa'ya dönüştürür , böylece herhangi bir GS değeri ile sıralanabilir .to_gs.to_s.
  • Bu gpushişlev, yerel Ruby numaralarını, dizeleri veya dizileri ilgili GS türlerine otomatik olarak sığdırmaz; bu nedenle, örneğin açıkça çağırıp sık sık kendiniz yapmanız gerekir Gstring.new(). Yığına GS değer türlerinden biri dışında bir şeyi iterseniz, daha sonra üzerinde işlem yapmaya çalışan herhangi bir kodun çökmesi olasıdır.

  • GS değer tipleri ayrıca, .factoryörneğin içeriklerini değiştirdikten sonra dizileri / dizgileri yeniden sarmak için yararlı olabilecek, türün yapıcısını çağıran bir yönteme sahiptir. Tüm tipler aynı zamanda tip zorlama uygulayan bir .coerceyönteme sahiptir : aynı tip içeren ve zorlanan bir çifti döndürür .a.coerce(b)ab

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.