Suma-resta de números dentro de una cadena

14

Tome una cadena como entrada y realice la suma / resta de todos los dígitos de la cadena y genere la suma de esas operaciones como resultado.

Reglas

  • Los dígitos de la cadena se leen de izquierda a derecha.
  • Si un dígito (n) es impar, realice la suma con el siguiente dígito (n + n1)
  • Si un dígito (n) es par, realice la resta con el siguiente dígito (n - n1)
  • Si ha alcanzado el último dígito en la cadena, realice la operación con el primer dígito en la cadena
  • La salida será la suma de todos los valores resultantes.
  • Si solo hay un dígito en la cadena, realice la operación consigo mismo (n + no nn)
  • Si no hay dígitos en la cadena, la salida es 0

Ejemplo

Input: r5e6o9mm!/3708dvc    
Process: (5+6) + (6-9) + (9+3) + (3+7) + (7+0) + (0-8) + (8-5)
Output: 32

Notas

  • Se acepta la función o el programa completo
  • La longitud máxima de entrada dependerá del límite de su idioma para una entrada de cadena
  • No hay restricciones en la entrada de caracteres, pero solo los dígitos de ancho medio cuentan para la salida
  • Pocos bytes ganan
Noir Antares
fuente
44
Un par de ejemplos más también serían buenos
dylnan
2
Recomiendo agregar un caso de prueba que termine con un dígito impar.
Arnauld
3
Caso_prueba sugerida: "", "0","1"
TSH
1
¿Podemos tomar la entrada como una matriz de caracteres en lugar de una cadena? (Julia hace una distinción entre esos dos.)
Sundar - Restablece a Mónica el
44
@sundar El consenso actual es que una cadena se define como una secuencia de caracteres. Entiendo que las matrices de caracteres están, por lo tanto, permitidas de manera predeterminada, incluso si su idioma tiene un tipo de cadena nativa .
Arnauld

Respuestas:

6

Jalea , 17 15 12 bytes

fØDV€ḂT‘ịƲSḤ

Pruébalo en línea!

Prueba los casos de prueba.

El programa mantiene solo los dígitos que siguen a un dígito impar y luego calcula el doble de la suma.

fØDV€ḂT‘ịƲSḤ   
f                   Remove anything that isn't...
 ØD                 a digit.
   V€               Cast each digit to an integer
         Ʋ          Monad:
     Ḃ              Parity of each digit.
      T             Indices of truthy elements (odd digits).
       ‘            Increment.
        ị           Index into list of digits.
                    Wraps to beginning and if there are no digits this returns 0.
          S         Sum.
           Ḥ        Double.
dylnan
fuente
3

K (oK) , 47 43 40 31 bytes

Solución:

{+/(1_x,*x)*2*2!x^:(x-:48)^!10}

Pruébalo en línea!

Explicación:

Elimine todo de la cadena que no sea un número (mientras que también convierte), módulo 2, multiplique por 2, multiplique con x girado por 1, y sume.

{+/(1_x,*x)*2*2!x^:(x-:48)^!10} / solution
{                             } / lambda taking implicit x
                           !10  / range 0..10
                          ^     / except
                   (     )      / do this together
                    x-:48       / subtract 48 from x (type fudging char ascii value -> ints), save back into x
                x^:             / x except right, and save back to x
              2!                / modulo 2
            2*                  / multiply by 2
           *                    / multiply by
   (      )                     / do this together
        *x                      / first element of x
       ,                        / append to
      x                         / x
    1_                          / drop first (ie rotate everything by 1)
 +/                             / sum, add (+) over (/)

Solución ingenua:

Elimine todo de la cadena que no sea un número (al mismo tiempo que convierte), tome una ventana deslizante de 2 elementos, descubra si son pares o impares, aplique sumar / restar según corresponda, luego resuma.

{+/((-;+)2!x).'2':(1+#x)#x^:(x-:48)^!10}

Pruébalo en línea!

Notas:

  • -4 bytes gracias a @ngn debido a una forma más inteligente de filtrar la entrada
  • -3 bytes usando una ventana deslizante en lugar de remodelar
  • -9 bytes portando la solución de ngn (enfoque no ingenuo)
callejero
fuente
1
x:48!x@&x in,/$!10->x^:(x-:48)^!10
ngn
Escribí la solución en q / kdb + y luego porté a OK ... ¡podría ser capaz de exprimir algunos bytes más de esto todavía!
StreetSter
1
Publiqué una respuesta por separado en ngn / k, siéntase libre de aportar ideas a partir de ahí. Creo que OK terminará siendo el más corto, ya que mi analizador es basura en este momento, no analiza correctamente la asignación modificada. Por cierto, no lo conocía ':como "ventana deslizante", interesante.
ngn
Parece que estás familiarizado con k. Si alguna vez tiene ganas de discutir cosas de programación de vectores con personas de ideas afines o simplemente ver a los demás discutir, tenemos esta sala de chat . La mayoría de las bromas son sobre APL, pero k y J también están en el tema.
ngn
2

Powershell, 80 78 76 bytes

($d="$args"-split'\D*'-ne'')+$d[0]|?{$p-match'[13579]';$p=$_}|%{$s+=2*$_};$s

-2 bytes gracias Neil con solución Retina

-2 bytes gracias AdmBorkBork

Script de prueba:

$f = {
($d="$args"-split'\D*'-ne'')+$d[0]|?{$p-match'[13579]';$p=$_}|%{$s+=2*$_};$s
}

&$f 'r5e6o9mm!/3708dvc'

Explicación

En primer lugar: debería agregar 2 * n si el dígito anterior es impar y 0 si un dígito anterior es par.

($d="$args"-split'\D*'-ne'')+ # let $d is array contains digits only, each element is a digit
$d[0]|                        # apend first digit to the end of the array
?{                            # where for each digit
    $p-match'[13579]'         # predicate is 'previous digit is odd' (it is false on the first iteration because $p is null)
    $p=$_                     # let previous digit is current
}|
%{                            # for each digit matched to the predicate
    $s+=2*$_                  # add current digit multiply 2 to $s. 
}
$s                            # return sum

Extra, 99 bytes

Inspirado por @Neil. Los dígitos de coincidencia de expresiones regulares con 'el dígito anterior es impar' solamente. MatchesEs una variable automática .

param($d)$d+($d-match'\d')+$Matches[0]|sls '(?<=[13579]\D*)\d'-a|%{$_.Matches.Value|%{$s+=2*$_}};$s
mazzy
fuente
1
Guarde un intercambio de bytes |?{$_}para -ne''y otro moviéndose $d="$args"-split'\D*'-ne''a parens como ($d="$args"-split'\D*'-ne'')+$d[0].
AdmBorkBork
2

MATL , 18 17 bytes

t4Y2m)!Ut1YSof)sE

Pruébalo en línea!

(-1 byte gracias a Luis Mendo / Giuseppe / ambos!)

Explicación:

     % Implicit input
 t   % duplicate input
     % stack: ['r5e6o9mm!/3708dvc' 'r5e6o9mm!/3708dvc']
 4Y2 % push inbuilt literal, characters '0':'9'
     % stack: ['r5e6o9mm!/3708dvc' 'r5e6o9mm!/3708dvc' '0123456789']
 m)  % extract only characters from input that belong to '0':'9'
     % stack: ['5693708']
 !U  % transpose and convert each value from string to number
     % stack: [5 6 9 3 7 0 8]
 t   % duplicate that
 1YS % circular shift by 1
     % stack: [[5 6 9 3 7 0 8] [8 5 6 9 3 7 0]]
 o   % parity check - 1 for odd, 0 for even
     % stack: [[5 6 9 3 7 0 8] [0 1 0 1 1 1 0]]
 f   % find non-zero value indices in last array
     % stack: [[5 6 9 3 7 0 8] [2 4 5 6]]
 )   % index at those places in the first array
 s   % sum
 E   % multiply by 2
     % (implicit) convert to string and display

La idea básica es que los números que siguen a los números pares se pueden ignorar, mientras que los que siguen a los números impares se duplican, y el resultado final es la suma de esos valores duplicados.

No pensé que fdespués de la verificación de paridad osería necesario, pero por alguna razón, MATL no ve la matriz de 0 y 1 que resultan de ouna matriz lógica, sino que los toma como índices e índices numéricos en posiciones 1y end.

sundar - Restablecer a Monica
fuente
Creo que puedes usar en !Ulugar de 48-. La transposición no parece hacer ningún daño aquí. opara la doubleentrada es justa mod(...,2), entonces la salida es double. Buen NaNtruco de entrada! Si eso está destinado a resolver la producción extraña en STDOUT, Dennis tuvo una idea y probablemente lo arregle pronto
Luis Mendo el
!Uen lugar de48-
Giuseppe
@LuisMendo welp, ¡me ganaste!
Giuseppe
@Giuseppe :-D :-D
Luis Mendo
Gracias a ambos, editado. @LuisMendo ¿Cuándo oda una salida de matriz lógica entonces, o no? (Debo confesar que nunca he investigado realmente el sistema de tipos numéricos de MATLAB). Y sí, pensé que NaNsería un buen centinela, ya que es poco probable que sea una entrada real en cualquier lugar, pero es bueno saber que no será necesario por mucho más tiempo. !
sundar - Restablece a Monica
2

K (ngn / k) , 33 bytes

{+/(1_x,*x)*2*2!x:-48+x^x^,/$!10}

Pruébalo en línea!

{ } es una función con argumento x

!10 es la lista 0 1 ... 9

$ convertir a cadenas

,/ concatenar

x^significa xsin lo que está a la derecha

x^x^significa xintersectado con lo que está a la derecha, es decir, mantener solo los dígitos dex

-48+ sustraer 48 , que es el código ASCII de"0"

x: asignar a x

2! mod 2

2* multiplicado por 2

1_x,*xes una gota de: xseguido de la primera de x; es decirx girado a la izquierda un paso

+/ suma

ngn
fuente
2

Japt (v2.0a0), 25 19 bytes

-6 bytes gracias a Shaggy .

kè\D
íÈ°*2*Y°u}Ué)x

Pruébalo aquí .

¡Funciona sin dígitos esta vez! La entrada es una lista de caracteres.

LegionMammal978
fuente
19 bytes , incluido el cambio a Japt v2. Sin xembargo, no estoy contento con la matriz en la función. Hazme ping en el chat si tienes alguna pregunta.
Shaggy
Espera, acabo de notar que esto no funcionará si la entrada no contiene ningún dígito.
Shaggy
Además, ¿dónde está la fuente de v2.0a0, @Shaggy? No puedo encontrarlo en el repositorio.
LegionMammal978
Esto es v1 y esto es v2.
Shaggy
En caso de que se lo haya perdido en el chat, lo reduje a 12 bytes .
Shaggy
2

05AB1E , 12 9 bytes

Ahorra 1 byte sobre el método ingenuo utilizando el truco de paridad de dylnan.
Guardado 3 bytes gracias al Sr. Xcoder

þDÁ€ÉÏSO·

Pruébalo en línea!

Explicación

þ              # push only digits of input
 D             # duplicate
  Á            # rotate right
   ۃ          # get the parity of each
     Ï         # keep only true items
      SO       # calculate digit-sum
        ·      # double
Emigna
fuente
Hmm, que þÀIþ€ÉÏSO·, þÀDÁ€ÉÏSO·, þÀ¹þ€ÉÏSO·o þÀsþ€ÉÏSO·pasar todos los casos de prueba para -2 bytes?
Sr. Xcoder
@ Mr.Xcoder: Ah, sí. ¡Agradable! Incluso podemos hacerlo þDÁ€ÉÏSO·por -3 :)
Emigna
1

Retina , 37 bytes

(\d).*
$&$1
L$`(?<=[13579]\D*).
2**
_

Pruébalo en línea! Explicación:

(\d).*
$&$1

Agregue un duplicado del primer dígito.

L$`(?<=[13579]\D*).

Haga coincidir cualquier cosa cuyo primer dígito anterior sea impar.

2**

Convierta todas las coincidencias en unarias y duplíquelas. (Los no dígitos se tratan como cero).

_

Toma la suma. Si no hubo coincidencias, esto produce cero según sea necesario.

Lo mejor que pude hacer en Retina 0.8.2 fue 44 bytes:

[^\d]

(.).*
$&$1
(?<![13579]).

.
$*
.
..
.

Pruébalo en línea! Explicación:

[^\d]

Eliminar no dígitos.

(.).*
$&$1

Agregue una copia del primer dígito.

(?<![13579]).

Eliminar dígitos que no siguen un dígito impar.

.
$*

Convierte a unario.

.
..

Doblarlos.

.

Toma la suma.

Neil
fuente
Me temo que el resultado será incorrecto si el último dígito no es impar
mazzy
1
@mazzy Cuando dice el último dígito, ¿quiere decir antes o después de copiar el primer dígito hasta el final?
Neil
'hasta el final'. el paso 'Añadir un duplicado del primer dígito' se está copiando al final? Okay. frio. Gracias
mazzy
1

JavaScript (ES6), 56 bytes

Toma entrada como una matriz de caracteres.

s=>s.map(c=>1/c?r+=p*(p=c*2&2,n=n||c,c):0,n=p=r=0)|r+p*n

Pruébalo en línea!

Comentado

s =>                     // given the input array s[]
  s.map(c =>             // for each character c in s[]:
    1 / c ?              //   if c is a digit:
      r +=               //     update r:
        p * (            //       p = either 0 or 2 (always 0 on the 1st iteration)
          p = c * 2 & 2, //       p = 0 if c is even, 2 if c is odd
          n = n || c,    //       if n is still equal to 0 (as an integer), set it to c
          c              //       compute p * c
        )                //     add the result to r
    :                    //   else:
      0,                 //     do nothing
    n = p = r = 0        //   n = first digit, p = previous digit, r = result
  )                      // end of map()
  | r + p * n            // compute the last operation with the 1st digit and add it to r
Arnauld
fuente
1

JavaScript (Node.js) , 85 84 83 82 bytes

-1 bytes gracias a ovs

s=>(s.match(/\d/g)||[]).reduce((r,n,i,a)=>r+(+n)+a[a[++i]!=null?i:0]*-(1-n%2*2),0)

Pruébalo en línea!

Toma la entrada de cadena, encuentra los dígitos como una matriz de caracteres o devuelve una matriz vacía si no se encuentra ninguna, y luego usa la coerción de tipo para garantizar que los valores se sumen / resten correctamente. La búsqueda directa aumenta el índice y utiliza una comprobación nula de brevedad, y luego la parte final verifica si el número es impar o par para luego forzar la suma o la resta (+ y - es -, etc.)

dedo azul
fuente
n-0puede ser+n
ovs
Bienvenido a PPCG!
Conor O'Brien
1

R , 58 bytes

function(x,y=strtoi(x[x%in%0:9]))sum(c(y[-1],y[1])*y%%2*2)

Pruébalo en línea!

digEmAll
fuente
67 bytes si no le importa la arraysalida.
Giuseppe
1
hmm, en realidad no puedes usar el producto punto debido a la matriz vacía, por xxxlo que son 68 bytes usando el cambio en la indexación apara generar y.
Giuseppe
@Giuseppe: modificado, gracias :)
digEmAll
@Giuseppe: Te pido tu opinión ya que eres un jugador de código más sabio ... de los comentarios parece que podemos usar un vector de caracteres, en este caso son posibles 61 bytes: ¡ Pruébalo en línea! Qué piensas ?
digEmAll
usar en strtoilugar de as.double, pero sí, eso debería estar bien.
Giuseppe
0

Perl 5 , 48 bytes

$;=$;[++$-%@;],$\+=$_%2?$_+$;:$_-$;for@;=/\d/g}{

Pruébalo en línea!

Me gusta cuán críptico se ve esto, pero es un bucle bastante sencillo alrededor de todos los números en la cadena.

Dom Hastings
fuente
0

C Sharp 180 bytes

Esto no es muy buen golf, jajaja.

s=>{var q=new Queue<int>(s.Where(Char.IsNumber).Select(n=>n-48));q.Enqueue(q.First());int t,o=0;o=q.Dequeue();try{while(true){t+=o+(o%2==0?-1:1)*(o=q.Dequeue());}}catch{return t;}}

Sin golf:

var q = new Queue<int>(s.Where(Char.IsNumber).Select(n=>n-48));
int t,o=0;

q.Enqueue(q.First());    
o=q.Dequeue();

try{
    while(true){
        t += o + (o%2==0?-1:1) * (o=q.Dequeue());
    }
}
catch {
    return t;
}
IEatBagels
fuente
0

Stax , 14 bytes

ÿ←«4é■≥B▬ê→█T♥

Ejecutar y depurarlo

Desempaquetado, sin golf y comentado, se ve así.

Vd|&    filter out non-digits
c|(\    zip into pairs after rotating right
F       for each digit pair
  B2%s  first-of-pair % 2, then swap top two stack elements
  eH*   eval digit as integer, double, then multiply
  +     add to running total

Ejecute este

recursivo
fuente
0

JavaScript (ES6), 52 bytes

s=>s.filter(t=>1/t&&~(a+=u*t,u=t%2),a=u=0)[0]*u+a<<1

Espera entrada como una matriz de caracteres. Advertencia: debido al uso de desplazamiento de bits, la salida tiene un límite superior de2^31-1

Pruébalo en línea!

Explicación

Esencialmente duplica la suma de los dígitos después de valores impares.

s => s.filter(             // filter to preserve the first digit
    t =>
        1/t &&             // short-circuits if NaN
        ~(                 // coerce to truthy value
            a += u * t,    // adds value only if previous digit is odd
            u = t%2        // store parity of current digit
        ),
    a = u = 0
)[0]                       // first digit
* u + a
<< 1                       // bit-shift to multiply by 2 (also coerces a NaN resulting from a string devoid of digits to 0)
redundancia
fuente