| Bytes | Lang | Time | Link |
|---|---|---|---|
| 363 | C gcc | 250527T032444Z | ceilingc |
| nan | Go | 250531T044532Z | user1280 |
| 467 | Rust | 250521T020016Z | ceilingc |
| 201 | Ruby | 250522T075107Z | Value In |
| 153 | Uiua | 240304T192036Z | jan |
| 209 | JavaScript Node.js | 240304T031642Z | tsh |
| 263 | JavaScript ES6 | 240303T174617Z | Arnauld |
| 116 | Charcoal | 240303T090238Z | Neil |
| 795 | JavaScript Node.js | 240302T015918Z | 2pichar |
| 117 | K ngn/k | 240229T174254Z | ovs |
C (gcc), 481 464 448 429 417 402 391 380 363 bytes
z=128;*strtok();atoi();*f(char*s){int a['2d']={},*b=a,*c,*k=a,i=0,m;char*p;for(;m=p=strtok(i++?0:s," ");)if(*p>47)*p>57?b[*p-z]=1:(*b=atoi(p),b+=z);else for(b-=m=z,c=b-z,*p>46?*c/=*b:*p%2?*c+=*b:(*c*=*b);--m;b[m]=0)if(*p-43)c[m]-=b[m]*(*p%2*2-1);else if(c[m]-b[m])return"*";for(p=s;k<b;k++,m%=z)p+=sprintf(p,"%c%2$d%3$s"+(m++?!*k*6:2),m,*k,(m<~-z)+" ");return s;}
Slightly less golfed.
*strtok(int*,int);atoi();
*f(char*s){
int a['2d']={},i=0,j=0,k=0,m;
for(char*p;p=strtok(i++?0:s," ");) // split input string
if(m=128,*p<48){ // +, * or /
j--;
if(*p-43) // * or /
for(*p-47?a[m*~-j]*=a[m*j]:(a[m*~-j]/=a[m*j]);--m;)
a[128*~-j+m]+=a[128*j+m]*(*p-47?1:-1);
else // +
if(a[~-j*m]+=a[j*m],bcmp(a+m*j+1,a+m*~-j+1,508))
return"*";
bzero(a+128*j,512);
}else
*p>57?a[m*~-j+*p]=1:(a[j++*m]=atoi(p)); // number or unit
for(i=0;m=k<j;strcat(s+i++," "),k++) // construct output
for(i+=sprintf(s+i,"%d",a[k<<7]);m<128;m++)
a[k*128+m]?i+=sprintf(s+i,"%c%d",m,a[k*128+m]):0;
return s;
}
Go, 665 519 518 513 502 500 498 bytes
Saved (146+1+5+11+2+2)=167 bytes thanks to @ceilingcat
Golfed version. Attempt This Online!
func f(x[]string)string{a,i,z:=make([]int,25600),0,256;var u strings.Builder;for _,t:=range x{if"0">t{i-=z;if"+">t{a[i-z]*=a[i]}else if"/">t{a[i-z]+=a[i]}else{a[i-z]/=a[i]};for m:=1;m<z;m++{if"+"==t{if a[i-z+m]!=a[i+m]{return"*"}}else{a[i-z+m]+=a[i+m]*map[string]int{"*":1,"/":-1}[t]};a[i+m]=0}}else if"A">t{fmt.Sscan(t,&a[i]);i+=z}else{a[i-z+int(t[0])]+=1}};for t:=range i{if a[t]!=0{if t%z>0{u.WriteByte(byte(t))};u.WriteString(strconv.Itoa(a[t]))};if-^t%z<1{u.WriteByte(' ')}};return u.String()}
Less golfed version. Attempt This Online!
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func f(x []string) string {
a := make([]int, 12800)
var u strings.Builder
i := 0
for _, t := range x {
if t < "0" { // +, * or /
i -= 1
if t == "+" { // + operator
for m := 1; m < 128; m++ {
if a[128*(i-1)+m] != a[128*i+m] {
return "*"
}
}
a[128*(i-1)] += a[128*i]
} else {
if t == "*" { // * operator
a[128*(i-1)] *= a[128*i]
for m := 1; m < 128; m++ {
a[128*(i-1)+m] += a[128*i+m]
}
} else { // / operator
a[128*(i-1)] /= a[128*i]
for m := 1; m < 128; m++ {
a[128*(i-1)+m] -= a[128*i+m]
}
}
}
for m := 1; m < 128; m++ {
a[128*i+m] = 0
}
} else if t < "A" { // numbers
val, _ := strconv.Atoi(t)
a[128*i] = val
i++
} else { // units
a[128*(i-1)+int(t[0])] += 1
}
}
for t := 0; t < i; t++ {
u.WriteString(strconv.Itoa(a[128*t]))
for v := 1; v < 128; v++ {
if a[128*t+v] != 0 {
u.WriteByte(byte(v))
u.WriteString(strconv.Itoa(a[128*t+v]))
}
}
u.WriteByte(' ')
}
return u.String()
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input := scanner.Text()
tokens := strings.Fields(input)
fmt.Println(f(tokens))
}
}
Rust, 1559 1514 1493 1448 1347 1306 663 609 580 564 538 508 492 484 467 bytes
fn f(x:&[&str])->String{let(mut a,mut u,mut i,z)=(vec![0;25600],format!(""),0,256);for t in x{if&"0">t{i-=z;match t{&"+"=>a[i-z]+=a[i],&"/"=>a[i-z]/=a[i],_=>a[i-z]*=a[i]}for m in 1..z{if&"+"!=t{a[i-z+m]+=a[i+m]*if&"/">t{1}else{-1}}else if a[i-z+m]!=a[i+m]{return format!("*")}a[i+m]=0}}else if&"A">t{a[i]=t.parse().unwrap();i+=z}else{a[t.as_bytes()[0]as usize+i-z]+=1}}for t in 0..i{if a[t]!=0{if t%z>0{u.push(t as u8 as char)}u+=&a[t].to_string()}if!t%z<1{u+=" "}}u}
Slightly less golfed:
fn f(x:&[&str])->String{
let mut a:[i32;12800]=[0;12800];
let(mut u,mut i)=(String::new(),0);
for t in x{
if&"0">t{ // +, * or /
i-=1;
if&"+"==t{ // + operator
for m in 1..128{
if a[128*(i-1)+m]!=a[128*i+m]{
return format!("*")
}
}
a[128*(i-1)]+=a[128*i]
}else{
if&"*"==t{ // * operator
a[128*(i-1)]*=a[128*i];
for m in 1..128{
a[128*(i-1)+m]+=a[128*i+m]
}
}else{ // / operator
a[128*(i-1)]/=a[128*i];
for m in 1..128{
a[128*(i-1)+m]-=a[128*i+m]
}
}
}
for m in 1..128{
a[128*i+m]=0
}
}else
if&"A">t{ // numbers
a[128*i]=str::parse::<i32>(t).unwrap();
i+=1
}else{ // units
a[128*(i-1)+(t.as_bytes()[0]as usize)]+=1
}
}
for t in 0..i{
u.push_str(&a[128*t].to_string());
for v in 1..128{
if a[128*t+v]!=0{
u.push(v as u8 as char);
u.push_str(&a[128*t+v].to_string())
}
}
u.push(' ')
}
u
}
Ruby, 201 bytes
Errors due to mismatched types when adding throw a NameError by calling the uninitialized variable X.
->i,*s{i.map{|o|o=~/[a-z]/?s[-1][1][o]=1:s<<(o=~/\d/?[o.to_i,{}]:(x,y=s.pop 2;a,b=x;c,d=y
[eval([a,c]*o),o==?+?b==d ?b:X: b&&d ?b.merge(d){o==?*?_2+_3: _2-_3}.reject{_2==0}:b||d]))}
s.map{[_1,*_2]*''}}
Attempt This Online! (prints * if it errors out)
Uiua, 204 192 178 153 characters
-12: remove error handling and output reversal and redundant spaces that the formatter always puts back in.
-14: use "uiuisms" page to golf character range, use content ◇ instead of unbox, and golf creation of the stack.
-25: Get less stingy with memory usage, etc.
P←⊙:⊙⊙°⊂∩°⊂°⊂◌
r←⇡27
a←⍜°⊂(@ ◌)+@`r
i←⊙(⟨⊂⊂⊓×+P|⊂⊂⊓+⟜(⍤"*"≍)P|◌|◌|◌|⊂⊂⊓÷-P|⟨⍜⊙°⊂+=a|⊂×=0r⋕⟩⍣(1◌⋕)0.⟩↧6/+-@*.):°□°⊂
(↘1/◇⊂♭≡(⨬(□""◌◌|□⊂⊙°⋕)≠0,a)◌⍥i⧻.:↯0r)
commented version with tests golfed version
P ← ⊙:⊙⊙°⊂∩°⊂°⊂ # pop 2 from small stack and separate number and units
r ← ⇡27
a ← ⍜°⊂(@ ◌)+@`r
i ← ⊙(
⨬(
⊂⊂⊓×+P◌ # times
| ⊂⊂⊓+⟜(⍤"*"≍)P◌ # plus
| ◌
| ◌
| ◌ # other characters
| ⊂⊂⊓÷-P◌ # divided by
| ⨬(
⍜⊙°⊂+=a # letter: add one to corresponding cell in top of small stack
| ⊂×=0r⋕ # number: push unitless number to small stack
)⍣(1◌⋕)0.
)↧6/+-@*. # ---the difference from star, or 6 if it's a number or letter
):°□°⊂ # process one token from the input
f ← (
◌⍥i⧻.:↯0r # setup the label and small stack
≡(⨬(□""◌◌|□⊂⊙°⋕)≠0,a) # append unit to each number in the small stack
↘1/◇⊂♭ # final concatenation
)
Input is a boxed array ({}) of token strings, or there is an extra string parsing function in the formatted version link.
JavaScript (Node.js), 209 bytes
p=>p.map(n=>a.push(y=+n?[+n,...Buffer(36)]:n<0+a.pop()?a.pop().map((o,i)=>(m=y[i],i)?n<'+'?o+m:n<'/'?o-m?E:o:o-m:eval(o+n+m)):(y[parseInt(n,36)]=1,y)),a=[])&&a.map(x=>x.reduce((x,v,i)=>v?x+i.toString(36)+v:x))
Input array of tokens, output array of values or throw error.
JavaScript (ES6), 263 bytes
s=>s.replace(/\S+/g,v=>v>{}?s[0][1]=[[v,1]]:s=[[(u=[])|v||([[y,q],[x,u],...s]=s,v+1|0?e|=u+''!=q:q.map(([U,e])=>(u.find(o=>o[0]==U)||u.push(o=[U,0])&&o)[1]+=v<"/"?e:-e),eval(x+v+y)),u.filter(o=>o[1]).sort()],...s],e=s=[])|e?"*":s.reverse().join` `.split`,`.join``
Charcoal, 123 116 bytes
F⪪S ¿Σι⊞υ⁺⟦Iι⟧Eβ⁰¿№βι§≔§υ±¹⊕⌕βι¹«≔⊟υζ≔⊟υη⊞υ∧∨⬤∧ζη∨¬λ⁼κ§ζλ⁻+ιE∧ζη⎇λ⁻κ×§ζλ⊖﹪℅ι³§⟦×κ§ζλ⁺κ§ζλ÷κ§ζλ⟧℅ι»Eυ⭆∨ι*⎇μ⎇λ⁺§β⊖μλωλ
Try it online! Link is to verbose version of code. Since the whole stack is output, I've effectively included several test cases in the link. Explanation:
F⪪S
Split the input on spaces and loop over the resulting tokens.
¿Σι⊞υ⁺⟦Iι⟧Eβ⁰
If this token is a positive integer, then push its value with zero exponents for all letters.
¿№βι§≔§υ±¹⊕⌕βι¹
Otherwise, if this token is a letter, then set the exponent for that letter to 1 for the latest value.
«
Otherwise:
≔⊟υζ≔⊟υη
Retrieve the two arguments.
⊞υ∧∨⬤∧ζη∨¬λ⁼κ§ζλ⁻+ιE∧ζη⎇λ⁻κ×§ζλ⊖﹪℅ι³§⟦×κ§ζλ⁺κ§ζλ÷κ§ζλ⟧℅ι
If the arguments are compatible or the operations is not sum, calculate the product, sum and quotient of the two arguments, selecting according to the ordinal of the token. (In the case of the exponents, the ordinal modulo 3 is decremented and multiplied by the second exponent, and this is subtracted from the first exponent.)
»Eυ⭆∨ι*⎇μ⎇λ⁺§β⊖μλωλ
For each value on the stack, concatenate its value with any non-zero exponents, unless the value was invalid, in which case output a *.
JavaScript (Node.js), 797 795 bytes
Z=require('util');O=Object;N="length";A=u=>O.fromEntries([...u.matchAll(/([a-zA-Z])(-?\d+)/g)].map(_=> _.slice(1)));B=u=>{s="";e=O.entries(u);for(i=0;i<e[N];i++){s+=e[i][0]+e[i][1]}return s};D=T=>{S=[];U=[];p=/[+*\/]/;for(t of T){if(/\d+/.test(t[0])||/\d+/.test(t[1])&&(t[0]=="-"||t[0]=="+")){S.push(t)}else if(p.test(t)){let[r,l]=[S.pop(),S.pop()];[h,H]=[U.pop(),U.pop()];if(H){f=A(h);g=A(H);m=1;if(t=="+"){if(Z.isDeepStrictEqual(g,f)){n=B(g)}else{return'*'}}if(t=="/"){m=-1}L=O.keys(g);P=O.keys(f);z={};for(i=0;i<L[N];i++){k=L[i];if(k in f){y=+g[k]+m*+f[k];y!=0?(z[k]=y):0}else{z[k]=+g[k]}}for(i=0;i<P[N];i++){k=P[i];if(!(k in z||k in g)){z[k]=m*+f[k]}}n=B(z);n!=""?U.push(n):0}S.push(""+eval(l+t+r))}else{if(t[N] > 1){U.push(t)}else{U.push(t+1)}}}return S.map((E,I)=> E+(U[I]||"")).join(" ")}
Try it online! Input is as an array of token strings passed to D. Output is to STDOUT. There's probably a shorter way, but this is what I've got (and JS is not a golfing language).
K (ngn/k), 134 124 117 bytes
{,//$x,(!y),'.y}.'|(){(,$[43=*y-*|&/=/h;E;1=C;**x;^[_%;.y].|*'h],(&~b)_b:(y!C;*|(1-3!*y)/h:C#x)2=C),(C:3!"0a"'*y)_x}/
Try it online! Input and output as list of strings, t converts between that and space separated format.