8
\$\begingroup\$

Cleaning the dishes

In this task, you will be given a bar of soap with a width of 1 or more units. You will also be given a plate, which you will have to clean, using the soap as few times as you can. The plate will be at least 1 character. You will have to output a plate with the 'clean' character representing the plate, and a third unique character to represent in what positions the bar of soap was placed.

How much the soap cleans:

(n-1)//2 on each side for odd n
(n-1)//2 on the left side of the soap bar for even n
n//2   on the right side of the soap bar for even n

Note: n//2 means floor(n/2).

Input

An integer greater than or equal to 1. A series of 2 unique characters to represent clean portions and dirty portions. Here, '=' represents a dirty portion, and '-' represents a clean portion. '+' represents where the soap was placed. Before the colon is what is the input, and after the colon is what is outputted.

IN : OUT

3 ===- : -+--
32 ================================ : ---------------+----------------
1 ==== : ++++
5 ----- : -----
4 -====- : --+---
3 -====- : --+-+-
7 === : +--
6 - : -
6 -==-===- : ---+----
5 -==--==- : ---+--+-
3 -==--==- : --+--+--

Rules

  • There are multiple solutions. Any one of them are acceptable, as long as they use the soap the minimum amount of times possible.
  • This is a contest, so the shortest answer in bytes wins!
  • Input may be whatever you want, as long as the plate and soap are specified, and clean/dirty portions of the plate are different. For example, strings and arrays of integers are allowed.
  • Output is of your choosing. You just need to make sure clean and soap portions of the output plate are different, but consistent. The plate and where the soap was placed should be shown.
  • Standard loopholes are not allowed.

Sandbox: Sandbox for Proposed Challenges

\$\endgroup\$
4
  • 5
    \$\begingroup\$ Does n//2 mean floor(n/2)? If it does, we would have \$0\$ on both sides for \$n=3\$, which would invalidate the 1st test case. So I guess you probably mean something else. \$\endgroup\$
    – Arnauld
    Commented Sep 15, 2019 at 23:37
  • 4
    \$\begingroup\$ Since it does not affect the core of the challenge I'd suggest (before too many answers appear) that (1) you allow an array/list of whatever two things we'd like to use as input and output and (2) to allow the input and output to use a total of two distinct values, so long as we specify what they are in each case (i.e. even {in:{clean:1; dirty:2}, out:{clean:2; soap:1}} makes sense as long as it's specified). \$\endgroup\$ Commented Sep 16, 2019 at 6:32
  • \$\begingroup\$ @Arnauld yes it does, fixed it. \$\endgroup\$
    – girobuz
    Commented Sep 17, 2019 at 4:00
  • 2
    \$\begingroup\$ @user1475369 It is not fixed yet. n//2-1 should be (n-1) // 2. \$\endgroup\$
    – Joel
    Commented Sep 17, 2019 at 7:50

6 Answers 6

4
\$\begingroup\$

JavaScript (ES6),  92 90 86  85 bytes

Saved 1 byte thanks to @Grimy

Takes input as (n)(string). Uses 1 as the soap character.

n=>s=>s.replace(eval(`/=.{0,${n-1}}/g`),s=>(g=n=>'-'.repeat(s.length-n>>1))(1)+1+g``)

Try it online!

How?

To get the widths of the cleaning areas, the helper function \$g\$ uses the expression \$\lfloor(n-k)/2\rfloor\$, which gives the left width for \$k=1\$ and the right width for \$k=0\$:

$$\lfloor (n-1)/2\rfloor=\cases{ (n-1)/2,&\text{if $n$ is odd}\\ n/2-1,&\text{if $n$ is even}\\ }$$

$$\lfloor (n-0)/2\rfloor=\cases{ (n-1)/2,&\text{ if $n$ is odd}\\ n/2,&\text{ if $n$ is even}\\ }$$

Commented

n =>                           // n = soap width
s =>                           // s = plate string
  s.replace(                   // find in s all patterns consisting of
    eval(`/=.{0,${n - 1}}/g`), //   '=' followed by 0 to n-1 characters (greedily)
    s =>                       //   for each pattern s:
      ( g = n =>               //     g is a function taking n = 0 or 1
          '-'.repeat(          //       and outputting a string of
            s.length - n >> 1  //       floor((s.length - n) / 2) hyphens
          )                    //
      )(1) +                   //     replace s with g(1) (left part)
      1 +                      //     followed by '1' (the soap)
      g``                      //     followed by g(0) (right part)
  )                            // end of replace()
\$\endgroup\$
2
  • \$\begingroup\$ (s.length-n)/2 to s.length-n>>1 for -1 byte. \$\endgroup\$
    – Grimmy
    Commented Sep 16, 2019 at 14:15
  • \$\begingroup\$ @Grimy I guess I was thinking no need to round because repeat does it for me, totally ignoring the fact that it was saving a byte... Thanks! \$\endgroup\$
    – Arnauld
    Commented Sep 16, 2019 at 14:29
1
\$\begingroup\$

Python 3, 86 bytes

def f(n,s):i=s.find('1');return~i and'0'*i+f'{2:0^{min(n,len(s)-i)}}'+f(n,s[n+i:])or s

Try it online!

Uses 0 for empty plate, 1 for dirt and 2 for soap. Takes an integer n and a string s as input.

The function searches for the first dirt character 1 in the string s. Starting at that point, it will format a string of emtpy plate characters 0 with a soap character 2 as the center character. Because of Python's string formatting rules, the soap character 2 will be in the center-left position when n is even. This piece of string will be of length n or the remaining number of characters in the input string s, whichever is shorter. The rest of the string s is evaluated recursively.

\$\endgroup\$
1
\$\begingroup\$

VBA, 157bytes

Sub a(s, p):z=Len(p):Q=s\2+s Mod 2-1
While instr(x+1,p,1)<>0
F=instr(x+1,p,1)
f=f+2/s
If f>Z then f=z
Mid(p,f)=2
X=f+q
Wend
P=replace(p,1,0)
Msgbox p
End sub

I think there are lots of bytes to save but couldn't get rid of the if Statement without causing some cases to fail

is Expecting the plate to be 0 clean and 1 dirty (2 is soap)

\$\endgroup\$
2
  • \$\begingroup\$ @TaylorScott code revised. - should have been = and a "s" was missing before mod. Thanks for catching that. \$\endgroup\$
    – JimmyJazzx
    Commented Jan 3, 2020 at 18:01
  • \$\begingroup\$ You can get this down further as Sub a(s,p):z=Len(p):q=(s-1.5)\2:While InStr(x+1,p,1):f=Instr(x+1,p,1)+2/s:f=IIf(f>z,z,f):Mid(p,f)=2:x=f+q:Wend:Debug.?Replace(p,1,0):End Sub for 140 bytes or as an Excel VBA Immediate Window function as p=[B1]:z=Len(p):q=[A1-1.5]\2:While InStr(x+1,p,1):f=InStr(x+1,p,1)+[2/A1]:f=IIf(f>z,z,f):Mid(p,f)=2:x=f+q:Wend:?Replace(p,1,0) for 126 bytes. Note that the immediate window function requires either a clean module, or that x be let back to the default value of 0 \$\endgroup\$ Commented Jan 22, 2020 at 13:19
0
\$\begingroup\$

Perl 5 (-p), 86, 59 bytes

-27 bytes thanks to Grimy,

$m=$_-1;s`=.{0,$m}`$_=$&;y/=/-/;s/(-*)-\1/$1+$1/r`ge;s;.* ;

TIO

  • $m=$_-1; input coerced to integer -1 which will be used as maximum number of character to be matched after =
  • s{=.{0,$m}}{...}e : subsitution of longest match of = followed by at most m characters
  • $_=$&;y/=/-/;s/(-*)-\1/$1+$1/r : to replace all = by - and then; to find the largest sequence of repeated - followed by a - and followed by the backreference \1
  • s;.* ;; : to remove the number and space from input

Previous answer

/ /;$m=$`-1;$p="{0,$m}";$_=$';s`=.$p`$l=length$&;"-"x(-!($l%2)+$l/2)."+"."-"x($l/2)`ge

TIO

other solution doesn't pass all tests because doesn't match clean parts within dirty.

67 bytes

/ /;$n=$`;$_=$';s/(=*)=(=?)\1(??{length$&>$n&&"^"})/$1+$2$1/g;y;=;-

TIO

\$\endgroup\$
2
  • \$\begingroup\$ -15 \$\endgroup\$
    – Grimmy
    Commented Sep 16, 2019 at 13:31
  • \$\begingroup\$ Down to 59 \$\endgroup\$
    – Grimmy
    Commented Sep 16, 2019 at 13:46
0
\$\begingroup\$

Jelly, 29 22 bytes

+þ_H}ḞFṬo³Ạ
JŒPçƇḢṬ+Ị{

Try it online!

A full program taking the dish as a string as its first argument and the size of the soap as an integer as its second argument. Prints a string representing the clean dish with the soap in place. For both, 0 is dirty, 1 is clean and 2 is soap.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Input and output may be a list of integers. \$\endgroup\$
    – girobuz
    Commented Sep 17, 2019 at 4:06
0
\$\begingroup\$

Retina 0.8.2, 69 bytes

\d+
$*-
^(-*)-\1
$1#$1
+`((((-)|#)+)-*,.*)(?<-4>.)*(?(4)$)=
$1$2
.+,

Try it online! Link includes test cases. Uses # to represent soap. Explanation:

\d+
$*-

Convert n into a template string of clean plate.

^(-*)-\1
$1#$1

Change the middle character of the template to soap.

+`

Repeatedly clean the plate until it cannot be cleaned any more.

((((-)|#)+)-*,.*)(?<-4>.)*(?(4)$)=

Match as much template and soap as possible. Keep track of the amount of template matched for later. The match starts as early as possible, so it will never start after the soap (since it could have matched starting at the soap in that case). Then optionally consume some clean template plate (meaning that the match must contain the soap) and an arbitrary amount before some dirty plate of exactly the same length as the template previously matched.

$1$2

Replace the dirty plate with the clean template and soap.

.+,

Delete the clean template and soap.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.