Polinomların Sembolik Farklılaşması


20

Sembolik Farklılaşma 1: Coefishin 'Gitti

Görev

Stdin'den (1 ° (p) <128) x cinsinden bir polinomu alan ve farklılaştıran bir program yazın. Giriş polinomu aşağıdaki formdaki bir dize olacaktır:

"a + bx + cx^2 + dx^3 +" ...

burada her terimin katsayısı bir tamsayıdır (-128 <a <128). Her terim bir boşluk, a + ve başka bir boşluk ile ayrılır; doğrusal ve sabit terimler yukarıdaki gibi görünür (yani, hayır x^0veya x^1). Terimler artan derece sırasına göre görünecek ve sıfır katsayılı güçler göz ardı edilecektir. 1 veya -1 katsayısına sahip tüm terimler bu katsayıyı açıkça gösterir.

Çıktınız tam olarak aynı forma sahip olmalıdır. Çıktıdaki katsayıların 127 * 127 == 16129 kadar büyük olabileceğini unutmayın.

Örnekler

"3 + 1x + 2x^2" ==> "1 + 4x"
"1 + 2x + -3x^2 + 17x^17 + -1x^107" ==> "2 + -6x + 289x^16 + -107x^106"
"17x + 1x^2" ==> "17 + 2x"

puanlama

Skorunuz, programınızın bayt cinsinden uzunluğudur, yerleşik veya sembolik cebir kullanan bir kütüphane kullanıyorsanız üç ile çarpılır.


Burada zaten bu zorluğa sahip olmadığımıza inanamıyorum!
flawr

5
@flawr Bir çeşit yaptık. (Her ne kadar diğer fonksiyonlar da gerekiyordu ve çıktı formatı üzerinde katı kurallar yoktu.)
Martin Ender

@flawr Aynı şeyi düşündüm ... ama yine de Martin'in bağlantılı yazı aramasını bulamadım. Ah güzel.
hYPotenuser

Yanıtlar:


15

Retina , 53 43 42 41 40 35 bayt

^[^x]+ |(\^1)?\w(?=1*x.(1+)| |$)
$2

Sayım amacıyla her satır ayrı bir dosyaya gider, ancak Retina'yı -sbayrakla çağırarak yukarıdakileri tek bir dosya olarak çalıştırabilirsiniz .

Bu, giriş dizesindeki sayıların tekli olarak verilmesini bekler ve çıktıyı aynı biçimde verir. Örneğin

1 + 11x + -111x^11 + 11x^111 + -1x^11111
-->
11 + -111111x + 111111x^11 + -11111x^1111

onun yerine

1 + 2x + -3x^2 + 2x^3 + -1x^5
-->
2 + -6x + 6x^2 + -5x^4

açıklama

Kod, temel olarak bir taneye sıkıştırılmış 4 sübstitüsyon olan tek bir regex sübstitüsyonunu tarif eder. Dallardan yalnızca birinin grubu dolduracağına $2, diğer üç eşleşmeden herhangi biri eşleşmenin dizeden silineceğine dikkat edin. Böylece dört farklı duruma ayrı ayrı bakabiliriz:

^[^x]+<space>
<empty>

Dize ile karşılaşmadan dizenin başlangıcından bir boşluğa ulaşmak mümkünse x, ilk terim sabit terimdir ve onu sileriz. Açgözlülüğü nedeniyle +, bu sabit terimden sonra artı ve ikinci boşlukla da eşleşecektir. Sabit bir terim yoksa, bu bölüm hiçbir zaman eşleşmeyecektir.

x(?= )
<empty>

Bu x, ardından gelen bir boşlukla, yani xdoğrusal terimin (varsa) eşleşir ve onu kaldırır. Bundan sonra bir boşluk olduğundan emin olabiliriz, çünkü polinom derecesi her zaman en az 2'dir.

1(?=1*x.(1+))
$1

Bu, katsayının üs tarafından çarpılmasını gerçekleştirir. Bu 1, katsayıdaki bir tekle eşleşir ve bunu ileriye doğru karşılık gelen üsün tamamıyla değiştirir.

(\^1)?1(?= |$)
<empty>

Bu, izlemeyi 1(ileriye dönük olarak sağlanır) eşleştirerek kalan tüm üsleri azaltır . Eşleştirmek ^11(ve bir kelime sınırı) mümkünse , bunun yerine, doğrusal terimi doğru bir şekilde göstermeye özen gösteririz.

Sıkıştırma için, koşulların çoğunun birbirini etkilemediğini fark ediyoruz. (\^1)?üçüncü durumda gözetleme doğruysa eşleşmez, bu yüzden bu ikisini bir araya getirebiliriz

(\^1)?1(?=1*x.(1+)| |$)
$2

Şimdi biz zaten ikinci durum için gerekli lookahead sahip ve eşleştirme yaparken diğerleri gerçek olamaz xbiz sadece genelleme böylece, 1bir karşı \w:

(\^1)?\w(?=1*x.(1+)| |$)
$2

İlk vakanın diğerleriyle ortak bir yanı yok, bu yüzden onu ayrı tutuyoruz.


9

CJam, 43 41 bayt

Qleu'^/';*'+/{~:E[*'x['^E(]]E<}/]1>" + "*

@ Jimmy23013 bir hata işaret ve iki bayt golf için teşekkürler!

CJam yorumlayıcısında çevrimiçi deneyin .

Nasıl çalışır

Q           e# Leave an empty array on the bottom of the stack.
l           e# Read a line from STDIN.
eu'^/';*    e# Convert to uppercase and replace carets with semicolons.
'+/         e# Split at plus signs.

{           e# For each resulting chunk:
  ~         e#   Evaluate it. "X" pushes 1 and ";" discards.
            e#   For example, "3X" pushes (3 1) and "3X;2" (3 2).
   :E       e#   Save the rightmost integer (usually the exponent) in E.
   [        e#
     *      e#   Multiply both integers.
            e#   For a constant term c, this repeats the empty string (Q) c times.
     'x     e#   Push the character 'x'.
     ['^E(] e#   Push ['^' E-1].
   ]        e#
   E<       e#  Keep at most E elements of this array.
            e#  If E == 1, 'x' and ['^' E-1] are discarded.
            e#  If E == 2, ['^' E-1] is discarded.
            e#  If E >= 3, nothing is discarded.
}/          e#

]           e# Wrap the entire stack in an array.
1>          e# Discard its first element.
            e# If the first term was constant, this discards [""]. ["" 'x']
            e# or ["" 'x' ['^' E-1]], depending on the constant.
            e# In all other cases, it discards the untouched empty array (Q).
" + "*      e# Join all kept array elements, separating by " + ".

5

Perl, 64 63 bayt

62b kodu + 1 komut satırı (-p)

Şu anda şaşırtıcı değil, ama kısaltmaya çalışacağım.

s/(\d+)x.(\d+)/$1*$2."x^".($2-1)/eg;s/\^1\b|^\d+ . |x(?!\^)//g

Kullanım örneği:

echo "1 + 2x + 3x^2" | perl -pe 's/(\d+)x.(\d+)/$1*$2."x^".($2-1)/eg;s/\^1\b|^\d+ . |x(?!\^)//g'

-1b için teşekkürler Denis


5

Julia, 220 bayt

Düzenli ifade yok!

y->(A=Any[];for i=parse(y).args[2:end] T=typeof(i);T<:Int&&continue;T==Symbol?push!(A,1):(a=i.args;c=a[2];typeof(a[3])!=Expr?push!(A,c):(x=a[3].args[3];push!(A,string(c*x,"x",x>2?string("^",ex-1):""))))end;join(A," + "))

Bu, bir dizeyi kabul eden ve bir dize döndüren bir lambda işlevi oluşturur. İç kısımlar Julia kodu değerlendirildiğinde ne olacağını taklit eder: bir dize sembollere, ifadelere ve çağrılara ayrıştırılır. Aslında tam bir Julia sembolik farklılaştırma işlevi yazmayı deneyebilir ve Julia'nın bir parçası olarak gönderebilirim.

Ungolfed + açıklaması:

function polyderiv{T<:AbstractString}(y::T)

    # Start by parsing the string into an expression
    p = parse(y)

    # Define an output vector to hold each differentiated term
    A = Any[]

    # Loop through the elements of p, skipping the operand
    for i in p.args[2:end]

        T = typeof(i)

        # Each element will be an integer, symbol, or expression.
        # Integers are constants and thus integrate to 0. Symbols
        # represent x alone, i.e. "x" with no coefficient or
        # exponent, so they integrate to 1. The difficulty here
        # stems from parsing out the expressions.

        # Omit zero derivatives
        T <: Int && continue

        if T == Symbol
            # This term will integrate to 1
            push!(A, 1)
        else
            # Get the vector of parsed out expression components.
            # The first will be a symbol indicating the operand,
            # e.g. :+, :*, or :^. The second element is the
            # coefficient.
            a = i.args

            # Coefficient
            c = a[2]

            # If the third element is an expression, we have an
            # exponent, otherwise we simply have cx, where c is
            # the coefficient.
            if typeof(a[3]) != Expr
                push!(A, c)
            else
                # Exponent
                x = a[3].args[3]

                # String representation of the differentiated term
                s = string(c*x, "x", x > 2 ? string("^", x-1) : "")

                push!(A, s)
            end
        end
    end

    # Return the elements of A joined into a string
    join(A, " + ")
end

3

C, 204162 bayt

#define g getchar()^10
h,e;main(c){for(;!h&&scanf("%dx%n^%d",&c,&h,&e);h=g?g?e?printf(" + "):0,0:1:1)e=e?e:h?1:0,e?printf(e>2?"%dx^%d":e>1?"%dx":"%d",c*e,e-1):0;}

Temel olarak her terimi ayrıştırın ve farklılaştırılmış terimi sırayla yazdırın. Yeterince açıksözlü.


2

JavaScript ES6, 108 bayt

f=s=>s.replace(/([-\d]+)(x)?\^?(\d+)?( \+ )?/g,(m,c,x,e,p)=>x?(c*e||c)+(--e?x+(e>1?'^'+e:''):'')+(p||''):'')

ES5 Snippet'i:

// ES5 version, the only difference is no use of arrow functions.
function f(s) {
  return s.replace(/([-\d]+)(x)?\^?(\d+)?( \+ )?/g, function(m,c,x,e,p) {
    return x ? (c*e||c) + (--e?x+(e>1?'^'+e:''):'') + (p||'') : '';
  });
}

[
  '3 + 1x + 2x^2',
  '1 + 2x + -3x^2 + 17x^17 + -1x^107',
  '17x + 1x^2'
].forEach(function(preset) {
  var presetOption = new Option(preset, preset);
  presetSelect.appendChild(presetOption);
});

function loadPreset() {
  var value = presetSelect.value;
  polynomialInput.value = value;
  polynomialInput.disabled = !!value;
  showDifferential();
}

function showDifferential() {
  var value = polynomialInput.value;
  output.innerHTML = value ? f(value) : '';
}
code {
  display: block;
  margin: 1em 0;
}
<label for="presetSelect">Preset:</label>
<select id="presetSelect" onChange="loadPreset()">
  <option value="">None</option>
</select>
<input type="text" id="polynomialInput"/>
<button id="go" onclick="showDifferential()">Differentiate!</button>
<hr />
<code id="output">
</code>


2

Python 2, 166 bayt

Evlat, olması gerekenden daha uzun görünüyor.

S=str.split
def d(t):e="^"in t and int(S(t,"^")[1])-1;return`int(S(t,"x")[0])*(e+1)`+"x"[:e]+"^%d"%e*(e>1)
print" + ".join(d(t)for t in S(raw_input()," + ")if"x"in t)

İşlev dsabit olmayan bir terim alır tve türevini döndürür. Ben deflambda kullanmak yerine fonksiyonun nedeni ben üs 1 eksi atamak olduğunue dört kez daha kullanılır. Ana can sıkıcı şey, Python 2'nin backtick operatörü buna yardımcı olmasına rağmen, dizeler ve ints arasında ileri geri atmak zorunda kalıyor.

Daha sonra girdiyi terimlere böleriz ve diçerdiği her birini çağırırız "x", böylece sabit terimi ortadan kaldırırız. Sonuçlar tekrar birleştirilir ve yazdırılır.


2

CJam, 62 57 55 49 bayt

Dennis, sitenin geri döndüğünü fark etmeden önce bunu utandırdı. Ama işte yaratılış zaten:

lS/{'x/:T,({T~1>:T{~T~*'xT~(:T({'^T}&}&" + "}&}/;

Son sürüm @Dennis tarafından önerilen kısayollarla birkaç bayt kaydeder (değişkenleri kullanın ve yerine boşlukta bölün +).

Çevrimiçi deneyin


1
Bir değişkeni kaydetmek, diğer bloğa atmaktan daha kısadır. Örneğin _({'^a\}{;}?, 1 bayt daha uzun :T({T'^a\}&.
Dennis

1
Artı işaretleri yerine boşluklara ayrılırsanız ~, geri kalan blokta ihtiyacınız yoktur ve bunu da ortadan kaldırabilirsiniz.
Dennis

@Dennis Bu işe yarıyor, teşekkürler. Başlangıçta artı işaretlerini ortadan kaldırmak istedim, ancak varlığını test ettiğimde yine de düşüyorlar x. Ben varken biraz daha iyileştirme buldum. Çoğunlukla, şimdi değişkenlerdeki değerlere sahip olduğum için, onları gerçekten ihtiyacım olan yerde hatırlayabilirim, bazı yığın manipülasyonlarını kaydederim. Daha aönce çıktı üretimini optimize ettiğimde silinmesi gereken bir başıma da sahiptim .
Reto Koradi

1

Pyth, 62 bayt

jJ" + "m::j"x^",*Fdted"x.1$"\x"x.0"kftTmvMcd"x^"c:z"x ""x^1 "J

Bazı regex ikameleri kullanarak oldukça çirkin çözüm.


1

Python 3, 176 bayt

s=input().split(' + ')
y='x'in s[0]
L=map(lambda x:map(int,x.split('x^')),s[2-y:])
print(' + '.join([s[1-y][:-1]]+['x^'.join(map(str,[a*b,b-1])).rstrip('^1')for a,b in L]))

Aslında, ana sıkıntı dizeler ve ints arasında dönüştürme yapmak zorunda. Ayrıca, sabit bir terim gerekiyorsa, kod yalnızca 153 bayt olur.


İlk cevap, DLosc'u yenmek için ateş ediyordu, oraya tam olarak ulaşamadı.
El'endia Starman

0

Python 2, 229 bayt

import os
print' + '.join([i,i[:-2]][i[-2:]=='^1'].replace('x^0','')for i in[`a*b`+'x^'+`b-1`for a,b in[map(int,a.split('x^'))for a in[[[i+'x^0',i+'^1'][i[-1]=='x'],i]['^'in i]for i in os.read(0,9**9).split(' + ')]]]if i[0]!='0')

0

Python 2, 174 bayt

print' + '.join(['%d%s%s'%(b[0]*b[1],'x'*(b[1]>1),'^%d'%(b[1]-1)*(b[1]>2))for b in[map(int,a.split('x^')if 'x^'in a else[a[:-1],1])for a in input().split(' + ')if 'x'in a]])

Ne yazık ki, DLosc'un split yöntemini yeniden adlandırma ve belirli bir işlevde farklılaştırma gerçekleştirme hilesi kodumu kısaltmıyor ...

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.