Display a linear combination: Difference between revisions

From Rosetta Code
Content added Content deleted
m (used a larger font to make it easier to read the superscripts and symbols, added other whitespace and highlighting, re-did the examples with more whitespace, reduced some verbiage, added a ;Task; (bold) header, added whitespace before the TOC.)
m (→‎{{header|REXX}}: changed/added comments and whitespace, changed indentations.)
Line 268: Line 268:


=={{header|REXX}}==
=={{header|REXX}}==
<lang rexx>/*REXX program displays a finite liner combination in an infinite vector basis*/
<lang rexx>/*REXX program displays a finite liner combination in an infinite vector basis. */
@.=.; @.1 = '1, 2, 3'
@.=.; @.1 = '1, 2, 3'
@.2 = '0, 1, 2, 3'
@.2 = '0, 1, 2, 3'
@.3 = '1, 0, 3, 4'
@.3 = '1, 0, 3, 4'
@.4 = '1, 2, 0'
@.4 = '1, 2, 0'
@.5 = '0, 0, 0'
@.5 = '0, 0, 0'
@.6 = 0
@.6 = 0
@.7 = '1, 1, 1'
@.7 = '1, 1, 1'
@.8 = '-1, -1, -1'
@.8 = '-1, -1, -1'
@.9 = '-1, -2, 0, -3'
@.9 = '-1, -2, 0, -3'
@.10= -1
@.10 = -1
do j=1 while @.j\==.; n=0 /*process each vector; zero element cnt*/
do j=1 while @.j\==.; n=0 /*process each vector; zero element cnt*/
y=space(translate(@.j,,',')) /*elide commas and superfluous blanks. */
y=space( translate(@.j, ,',') ) /*elide commas and superfluous blanks. */
$= /*nullify output (liner combination).*/
$= /*nullify output (liner combination).*/
do k=1 for words(y); #=word(y,k) /* ◄───── process each of the elements.*/
do k=1 for words(y); #=word(y, k) /* ◄───── process each of the elements.*/
if #=0 then iterate; a=abs(x/1) /*if the value is zero, then ignore it.*/
if #=0 then iterate; a=abs(# / 1) /*if the value is zero, then ignore it.*/
s='+ '; if #<0 then s='- ' /*define the sign: plus(+) or minus(-)*/
s='+ '; if #<0 then s='- ' /*define the sign: plus(+) or minus(-)*/
n=n+1; if n==1 then s=strip(s) /*if the 1st element used, remove plus.*/
n=n+1; if n==1 then s=strip(s) /*if the 1st element used, remove plus.*/
if a\==1 then s=s || a'*' /*if multiplier is unity, then ignore #*/
if a\==1 then s=s || a'*' /*if multiplier is unity, then ignore #*/
$=$ s'e('k")" /*construct a liner combination element*/
$=$ s'e('k")" /*construct a liner combination element*/
end /*k*/
end /*k*/


$=strip(strip($), 'L', "+") /*strip leading plus sign (1st element)*/
$=strip( strip($), 'L', "+") /*strip leading plus sign (1st element)*/
if $=='' then $=0 /*handle special case of no elements. */
if $=='' then $=0 /*handle special case of no elements. */
say right(space(@.j), 20) ' ──► ' strip($) /*align the output.*/
say right( space(@.j), 20) ' ──► ' strip($) /*align the output for presentation. */
end /*j*/
end /*j*/
/*stick a fork in it, we're all done.*/</lang>
/*stick a fork in it, we're all done. */</lang>
'''output''' &nbsp; when using the default inputs:
'''output''' &nbsp; when using the default inputs:
<pre>
<pre>

Revision as of 23:05, 10 July 2016

Display a linear combination is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Display a finite   linear combination   in an infinite vector basis   .

Write a function that,   when given a finite list of scalars   ,
creates a string representing the linear combination     in an explicit format often used in mathematics, that is:

where


The output must comply to the following rules:

  •   don't show null terms, unless the whole combination is null.
e(1)     is fine,     e(1) + 0*e(3)     or     e(1) + 0     is wrong.
  •   don't show scalars when they are equal to one or minus one.
e(3)     is fine,     1*e(3)     is wrong.
  •   don't prefix by a minus sign if it follows a preceding term.   Instead you use subtraction.
e(4) - e(5)     is fine,     e(4) + -e(5)     is wrong.


Show here output for the following lists of scalars:

 1)    1,  2,  3
 2)    0,  1,  2,  3
 3)    1,  0,  3,  4
 4)    1,  2,  0
 5)    0,  0,  0
 6)    0
 7)    1,  1,  1
 8)   -1, -1, -1
 9)   -1, -2,  0, -3
10)   -1



EchoLisp

<lang scheme>

build an html string from list of coeffs

(define (linear->html coeffs)

   (define plus #f) 
   (or* 
   (for/fold (html "") ((a coeffs) (i (in-naturals 1)))
     (unless (zero? a)
		(set! plus (if plus "+" "")))
     (string-append html

(cond ((= a 1) (format "%a e%d " plus i)) ((= a -1) (format "- e%d " i)) ((> a 0) (format "%a %d*e%d " plus a i)) ((< a 0) (format "- %d*e%d " (abs a) i)) (else ""))))

    "0"))

(define linears '((1 2 3)

  (0 1 2 3)
  (1 0 3 4)
  (1 2 0)
  (0 0 0)
  (0)
  (1 1 1)
  (-1 -1 -1)
  (-1 -2 0 -3)
  (-1)))
  

(define (task linears)

   (html-print ;; send string to stdout
   (for/string ((linear linears))
     (format "%a -> %a 
" linear (linear->html linear)))))

</lang>

Output:

(1 2 3) -> e1 + 2*e2 + 3*e3
(0 1 2 3) -> e2 + 2*e3 + 3*e4
(1 0 3 4) -> e1 + 3*e3 + 4*e4
(1 2 0) -> e1 + 2*e2
(0 0 0) -> 0
(0) -> 0
(1 1 1) -> e1 + e2 + e3
(-1 -1 -1) -> - e1 - e2 - e3
(-1 -2 0 -3) -> - e1 - 2*e2 - 3*e4
(-1) -> - e1

Elixir

<lang elixir>defmodule Linear_combination do

 def display(coeff) do
   Enum.with_index(coeff)
   |> Enum.map_join(fn {n,i} ->
        {m,s} = if n<0, do: {-n,"-"}, else: {n,"+"}
        case {m,i} do
          {0,_} -> ""
          {1,i} -> "#{s}e(#{i+1})"
          {n,i} -> "#{s}#{n}*e(#{i+1})"
        end
      end)
   |> String.lstrip(?+)
   |> case do
        ""  -> IO.puts "0"
        str -> IO.puts str
      end
 end

end

coeffs =

 [ [1, 2, 3],
   [0, 1, 2, 3],
   [1, 0, 3, 4],
   [1, 2, 0],
   [0, 0, 0],
   [0],
   [1, 1, 1],
   [-1, -1, -1],
   [-1, -2, 0, -3],
   [-1]
 ]

Enum.each(coeffs, &Linear_combination.display(&1))</lang>

Output:
e(1)+2*e(2)+3*e(3)
e(2)+2*e(3)+3*e(4)
e(1)+3*e(3)+4*e(4)
e(1)+2*e(2)
0
0
e(1)+e(2)+e(3)
-e(1)-e(2)-e(3)
-e(1)-2*e(2)-3*e(4)
-e(1)

J

Implementation:

<lang J>fourbanger=:3 :0

 e=. ('e(',')',~])@":&.> 1+i.#y
 firstpos=. 0< {.y-.0
 if. */0=y do. '0' else. firstpos}.;y gluedto e end.

)

gluedto=:4 :0 each

 pfx=. '+-' {~ x<0
 select. |x
   case. 0 do. 
   case. 1 do. pfx,y
   case.   do. pfx,(":|x),'*',y
 end.

)</lang>

Example use:

<lang J> fourbanger 1 2 3 e(1)+2*e(2)+3*e(3)

  fourbanger 0 1 2 3

e(2)+2*e(3)+3*e(4)

  fourbanger 1 0 3 4

e(1)+3*e(3)+4*e(4)

  fourbanger 0 0 0

0

  fourbanger 0

0

  fourbanger 1 1 1

e(1)+e(2)+e(3)

  fourbanger _1 _1 _1

-e(1)-e(2)-e(3)

  fourbanger _1 _2 0 _3

-e(1)-2*e(2)-3*e(4)

  fourbanger _1

-e(1)</lang>

Perl 6

<lang perl6>sub linear-combination(@coeff) {

   (@coeff Z=> map { "e($_)" }, 1 .. *)
   .grep(+*.key)
   .map({ .key ~ '*' ~ .value })
   .join(' + ')
   .subst('+ -', '- ', :g)
   .subst(/<|w>1\*/, , :g)
       || '0'

}

say linear-combination($_) for [1, 2, 3], [0, 1, 2, 3], [1, 0, 3, 4], [1, 2, 0], [0, 0, 0], [0], [1, 1, 1], [-1, -1, -1], [-1, -2, 0, -3], [-1 ]

</lang>
Output:
e(1) + 2*e(2) + 3*e(3)
e(2) + 2*e(3) + 3*e(4)
e(1) + 3*e(3) + 4*e(4)
e(1) + 2*e(2)
0
0
e(1) + e(2) + e(3)
-e(1) - e(2) - e(3)
-e(1) - 2*e(2) - 3*e(4)
-e(1)

Python

<lang python> def linear(x):

   return ' + '.join(['{}e({})'.format('-' if v == -1 else  if v == 1 else str(v) + '*', i + 1)
       for i, v in enumerate(x) if v] or ['0']).replace(' + -', ' - ')

list(map(lambda x: print(linear(x)), [[1, 2, 3], [0, 1, 2, 3], [1, 0, 3, 4], [1, 2, 0],

       [0, 0, 0], [0], [1, 1, 1], [-1, -1, -1], [-1, -2, 0, 3], [-1]]))

</lang>

Output:
e(1) + 2*e(2) + 3*e(3)
e(2) + 2*e(3) + 3*e(4)
e(1) + 3*e(3) + 4*e(4)
e(1) + 2*e(2)
0
0
e(1) + e(2) + e(3)
-e(1) - e(2) - e(3)
-e(1) - 2*e(2) + 3*e(4)
-e(1)

Racket

<lang racket>#lang racket/base (require racket/match racket/string)

(define (linear-combination->string es)

 (let inr ((es es) (i 1) (rv ""))
   (match* (es rv)
     [((list) "") "0"]
     [((list) rv) rv]
     [((list (? zero?) t ...) rv)
      (inr t (add1 i) rv)]
     [((list n t ...) rv)
      (define ±n
        (match* (n rv)
          ;; zero is handled above
          [(1 "") ""]
          [(1 _) "+"]
          [(-1 _) "-"]
          [((? positive? n) (not "")) (format "+~a*" n)]
          [(n _) (format "~a*" n)]))
      (inr t (add1 i) (string-append rv ±n "e("(number->string i)")"))])))

(for-each

(compose displayln linear-combination->string)
'((1 2 3)
  (0 1 2 3)
  (1 0 3 4)
  (1 2 0)
  (0 0 0)
  (0)
  (1 1 1)
  (-1 -1 -1)
  (-1 -2 0 -3)
  (-1)))

</lang>

Output:
e(1)+2*e(2)+3*e(3)
e(2)+2*e(3)+3*e(4)
e(1)+3*e(3)+4*e(4)
e(1)+2*e(2)
0
0
e(1)+e(2)+e(3)
-e(1)-e(2)-e(3)
-e(1)-2*e(2)-3*e(4)
-e(1)

REXX

<lang rexx>/*REXX program displays a finite liner combination in an infinite vector basis. */ @.=.; @.1 = '1, 2, 3'

                                 @.2  =   '0, 1, 2, 3'
                                 @.3  =   '1, 0, 3, 4'
                                 @.4  =   '1, 2, 0'
                                 @.5  =   '0, 0, 0'
                                 @.6  =    0
                                 @.7  =   '1, 1, 1'
                                 @.8  =  '-1, -1, -1'
                                 @.9  =  '-1, -2, 0, -3'
                                 @.10 =   -1
 do j=1  while  @.j\==.;             n=0        /*process each vector; zero element cnt*/
 y=space( translate(@.j, ,',') )                /*elide commas and superfluous blanks. */
 $=                                             /*nullify  output  (liner combination).*/
     do k=1  for words(y);   #=word(y, k)       /* ◄───── process each of the elements.*/
     if #=0  then iterate;   a=abs(# / 1)       /*if the value is zero, then ignore it.*/
     s='+ ';      if #<0  then s='- '           /*define the sign:  plus(+) or minus(-)*/
     n=n+1;       if n==1 then s=strip(s)       /*if the 1st element used, remove plus.*/
     if a\==1             then s=s || a'*'      /*if multiplier is unity, then ignore #*/
     $=$  s'e('k")"                             /*construct a liner combination element*/
     end   /*k*/
 $=strip( strip($), 'L', "+")                   /*strip leading plus sign (1st element)*/
 if $==  then $=0                             /*handle special case of no elements.  */
 say right( space(@.j), 20)  ' ──► '   strip($) /*align the output for presentation.   */
 end      /*j*/
                                                /*stick a fork in it,  we're all done. */</lang>

output   when using the default inputs:

             1, 2, 3  ──►  e(1) + 2*e(2) + 3*e(3)
          0, 1, 2, 3  ──►  e(2) + 2*e(3) + 3*e(4)
          1, 0, 3, 4  ──►  e(1) + 3*e(3) + 4*e(4)
             1, 2, 0  ──►  e(1) + 2*e(2)
             0, 0, 0  ──►  0
                   0  ──►  0
             1, 1, 1  ──►  e(1) + e(2) + e(3)
          -1, -1, -1  ──►  -e(1) - e(2) - e(3)
       -1, -2, 0, -3  ──►  -e(1) - 2*e(2) - 3*e(4)
                  -1  ──►  -e(1)

Tcl

This solution strives for legibility rather than golf.

<lang Tcl>proc lincom {factors} {

   set exp 0
   set res ""
   foreach f $factors {
       incr exp
       if {$f == 0} {
           continue
       } elseif {$f == 1} {
           append res "+e($exp)"
       } elseif {$f == -1} {
           append res "-e($exp)"
       } elseif {$f > 0} {
           append res "+$f*e($exp)"
       } else {
           append res "$f*e($exp)"
       }
   }
   if {$res eq ""} {set res 0}
   regsub {^\+} $res {} res
   return $res

}

foreach test {

   {1 2 3}
   {0 1 2 3}
   {1 0 3 4}
   {1 2 0}
   {0 0 0}
   {0}
   {1 1 1}
   {-1 -1 -1}
   {-1 -2 0 -3}
   {-1}

} {

   puts [format "%10s -> %-10s" $test [lincom $test]]

}</lang>

Output:
     1 2 3 -> e(1)+2*e(2)+3*e(3)
   0 1 2 3 -> e(2)+2*e(3)+3*e(4)
   1 0 3 4 -> e(1)+3*e(3)+4*e(4)
     1 2 0 -> e(1)+2*e(2)
     0 0 0 -> 0         
         0 -> 0         
     1 1 1 -> e(1)+e(2)+e(3)
  -1 -1 -1 -> -e(1)-e(2)-e(3)
-1 -2 0 -3 -> -e(1)-2*e(2)-3*e(4)
        -1 -> -e(1)     

zkl

Translation of: Perl 6

<lang zkl>fcn linearCombination(coeffs){

  [1..].zipWith(fcn(n,c){ if(c==0) "" else "%s*e(%s)".fmt(c,n) },coeffs)
     .filter().concat("+").replace("+-","-").replace("1*","")
  or 0

}</lang> <lang zkl>T(T(1,2,3),T(0,1,2,3),T(1,0,3,4),T(1,2,0),T(0,0,0),T(0),T(1,1,1),T(-1,-1,-1),

 T(-1,-2,0,-3),T(-1),T)

.pump(Console.println,linearCombination);</lang>

Output:
e(1)+2*e(2)+3*e(3)
e(2)+2*e(3)+3*e(4)
e(1)+3*e(3)+4*e(4)
e(1)+2*e(2)
0
0
e(1)+e(2)+e(3)
-e(1)-e(2)-e(3)
-e(1)-2*e(2)-3*e(4)
-e(1)
0