Be respectful in the restroom

35

2

Of course, the SE network is very knowledgeable about how to be respectful in the restroom, but for those of you who need a recap, being respectful means flushing the toilet, etc. Most importantly, though, it means using the stall as far away from others as possible.

The challenge

Given a blueprint of a set of stalls with indications of which ones are in use as a string, you must return or print from a function or program where the most respectful place to do your business is.

The input

 0 1 2 3 4 5    <- The stall number which is not actually visible in the input. 
| | |-| |-|-|   <- the stalls

The stalls are numbered in ascending order from left to right. There will always be at least one empty stall. There can be up to 50 stalls in an input. You can also take the input as an array or string of 0s and 1s or booleans if you prefer to do so.

Stalls in use have - in them (in between the pipes).

The output

The most respectful stall to go to is the one that is on average farthest away from the ones in use. The distance between two stalls is the absolute value of the difference of the numbers above them.

Just to be clear: you are finding the average distance from all of the stalls—not just the neighboring ones.

You must output the lowest number of the most respectful stall to go to that is empty.

Examples

Input:
|-| |-| OR 101
Output:
1

Input:
| | |-| |-|-| OR 001011
Output:
0

Input:
|-| |-| | | | |-|-| OR 101000011
Output:
1

Input: 
|-| | | | | |-|-| | | | | OR 100000110000
Output:
11

Input:
|-|-|-|-| | | | | | |-| OR 11110000001
Output:
9

Input:
|-| | OR 10
Output:
1

Input:
|-| | |-| OR 1001
Output:
1

This is , so shortest code in bytes wins!

You can use 0 or 1 based indexing in your answer — whichever you prefer; if you use 1 based indexing, then you must say so explicitly in your answer.

Daniel

Posted 2016-08-09T15:58:49.743

Reputation: 6 425

Related, but not a dupe – Daniel – 2016-08-09T15:59:48.907

35"Of course, the SE network is very knowledgeable about how to be respectful in the restroom" [citation needed] – Alex A. – 2016-08-09T16:33:52.823

Are ties broken to the left or to the right? Specifically, does 1001 return 1 or 2? – Leaky Nun – 2016-08-09T16:45:44.623

7

@AlexA.: Have a look at the toilet questions and answers on travel.stackexchange to assess the level of education of the SE network (or to educate yourself).

– Jonas – 2016-08-09T17:05:25.550

Can the numbers in the input by separated with spaces? (0 1 0 1 0 0 for instance) – Dada – 2016-08-09T17:15:32.557

30But everyone knows that the respectfulness criterion is to maximize the minimun distance, not the average :-) – Luis Mendo – 2016-08-09T17:26:46.103

@Dada, I suppose so – Daniel – 2016-08-09T17:33:45.510

I'm getting these results. Am I misunderstanding something?

– Dennis – 2016-08-09T17:42:21.607

@Dennis Are you maximizing the average distance? My first hunch was to maximize the minimum – Luis Mendo – 2016-08-09T17:46:08.907

1@LuisMendo Yeah, that was indeed the problem. Thanks! – Dennis – 2016-08-09T17:50:34.330

2@Dopapp You should add [1,0,0,1] as a test case. None of the current test cases verifies if ties are broken correctly. – Dennis – 2016-08-09T17:52:53.593

8Why does 101000011 return 1 (instead of 4 or 5)? – Amani Kilumanga – 2016-08-10T04:02:23.013

@AmaniKilumanga, doing it on paper, 1 is correct. Are you calculating the maximum average distance or the maximum distance period? – Daniel – 2016-08-10T13:16:05.293

1Just a short note while browsing over random stackexchange questions, the average distance is indeed a strange criterion. The solution will always be either the first or the last free spot. (If there are more used stalls on my right than on the left, then moving left will always increase the distance and vice versa, with the minimum distance being somewhere in the middle) I'm no real code golfer, but maybe someone could use this for a shorter solution. – mlk – 2016-08-10T15:06:36.383

@Dopapp The expected output is the lowest stall number that is most respectful. In the case of 101000011, outputting 1 would be the LEAST respectful stall, with an average distance of 1, whereas 4 and 5 both have an average distance of 2.5, and the lower of the two is 4, so 4 is the expected output. – ewok – 2016-08-10T16:27:10.870

2@ewok, no. It is the average distance from all of the stalls--not just the neighboring ones. – Daniel – 2016-08-10T17:55:15.150

@Dopapp Ok then. That's not really clear from the question. I'd recommend clarifying it. – ewok – 2016-08-10T17:57:18.570

2@ewok, I have edited the question to be clearer – Daniel – 2016-08-10T17:59:29.267

2Being respectful in restrooms nowadays bring in complicated issues of gender identity. – Kaz – 2016-08-10T18:56:07.503

Answers

11

Jelly, 10 9 bytes

JạþTS׬MḢ

Uses 1-based indexing. Try it online! or verify all test cases.

How it works

JạþTS׬MḢ  Main link. Argument: A (array of Booleans)

J          Yield all indices of A.
   T       Yield all truthy indices of A.
 ạþ        Compute the table of absolute differences.
    S      Compute the sums of all columns.
           For each index, this yields the sum of all distances to occupied stalls.
     ׬    Multiply each sum by the logical NOT of the corresponding Boolean in A.
           This zeroes sums that correspond to occupied stalls.
       M   Maximal; yield an array of all indices of maximal sums.
        Ḣ  Head; extract the first index.

Dennis

Posted 2016-08-09T15:58:49.743

Reputation: 196 637

I believe that's 9 characters, not 9 bytes. – René Nyffenegger – 2016-08-11T07:05:48.823

Jelly uses a custom code page that encodes the only characters it understands as a single byte each. The bytes link in the header points to it. – Dennis – 2016-08-11T15:06:51.220

I was unaware of this... thanks for pointing it out. – René Nyffenegger – 2016-08-11T19:45:13.013

@Dennis Did you make an auto-comment userscript so you can just click on "Jelly bytes comment" and it will post it? – NoOneIsHere – 2016-08-12T16:02:11.577

@NoOneIsHere I do have that userscript (not mine), but I didn't add this one yet. I probably should though...

– Dennis – 2016-08-12T16:04:51.747

6

Swift, 158, 157, 128, 100 Bytes

Takes input from the Array<Bool> variable i, returns answer from the last expression.

let e=i.characters.map{$0>"0"}.enumerate()
e.flatMap{$1 ?nil:$0}.map{a in(a,e.flatMap{$1 ?$0:nil}.map{abs(a-$0)}.reduce(0){$0+$1})}.maxElement{$0.1 < $1.1}!.0

Edit 1:

Saved a byte by converting to bools via string comparison

let e=i.characters.map{$0=="1"}.enumerate()
e.flatMap{$1 ?nil:$0}.map{a in(a,e.flatMap{$1 ?$0:nil}.map{abs(a-$0)}.reduce(0){$0+$1})}.maxElement{$0.1 < $1.1}!.0

Edit 2:

Reworked my algorithm:

let e=i.characters.map{$0=="1"}.enumerate()
e.map{x in(x.0,x.1 ?0:e.reduce(0){$1.1 ?$0+abs(x.0-$1.0):$0})}.max{$0.1<$1.1}!.0

Edit 3:

Took advantage of new rule that allows taking input directly from a boolean array.

let e=i.enumerated()
e.map{x in(x.0,x.1 ?0:e.reduce(0){$1.1 ?$0+abs(x.0-$1.0):$0})}.max{$0.1<$1.1}!.0

Ungolfed:

// for the sake of easier copy/pasting of input, take it as string
let s = "100000110000"

// convert input to true for taken, false for free
// this is the input the golfed version actually uses
let input = s.characters.map{$0>"0"}

// Returns an array of tuples storing the array values (vacancy of the stall) and their index (their location)
let valueIndexPairs = bools.enumerated()

// Returns an array of pairs of locations and their avg distance to others
let locationDistancePairs = valueIndexPairs.map{(valueIndexPair: (Int, Bool)) -> (Int, Int) in

    let averageDistance = valueIndexPairs.reduce(0) {partialSum, otherStall in

        let otherStallIsTaken = otherStall.1

        if otherStallIsTaken {
            //don't let other stalls effect average if they're taken
            return partialSum
        }
        else {
            let thisStallLocation = valueIndexPair.0
            let otherStallLocation = otherStall.0
            let distanceToOtherStall = abs(thisStallLocation - otherStallLocation)
            return partialSum + distanceToOtherStall 
        }       
    }

    //if this stall is taken, treat its average distance to others as 0
    let thisStallsLocation = valueIndexPair.0
    let isThisStallTaken = valueIndexPair.1
    return (thisStallsLocation, isThisStallTaken ? 0 : averageDistance)
}

//find location where average distance is maxiumum
let bestLocationIndexPair = locationDistancePairs.max{$0.1 < $1.1}!

let bestLocation = bestLocationIndexPair.0

print(bestLocation)

Alexander - Reinstate Monica

Posted 2016-08-09T15:58:49.743

Reputation: 481

2I like swift answers – downrep_nation – 2016-08-10T10:22:03.070

It's fun to learn :) Although it tends to be a pretty painful language for golfing. The standard library is truly minimal (you're intended to use Foundation most of the time), the language is meant to be very expressive, and it's statically typed. The closure syntax is REALLY good though – Alexander - Reinstate Monica – 2016-08-10T14:18:20.393

I should probably explain how this code works lol – Alexander - Reinstate Monica – 2016-08-10T14:19:54.027

1@downrep_nation I added the ungolfed verison, in case you're interested – Alexander - Reinstate Monica – 2016-08-10T19:44:49.340

Perhaps save 3 bytes by removing "let" idk if you do need it or not, but from what I understand you do not need "let" which only serves as an indicator of a constant value – Rohan Jhunjhunwala – 2016-08-11T01:08:38.540

@RohanJhunjhunwala Unfortunately (for the sake of golfing, but fortunately for the sake of production code), Swift requires constants be declared with let, and variables with var. Either way it's a 4 byte hit – Alexander - Reinstate Monica – 2016-08-11T01:13:17.580

@ErikE From the question: "You can also take the input as am array of string of 0s and 1s or booleans if you prefer to do so." – Alexander - Reinstate Monica – 2016-08-11T10:58:15.000

5

Jelly, 13 bytes

1-indexed.

³Tạ⁸S
JUÇÞḟTṪ

Try it online!

Algorithm

Naive implementation of the question.

Leaky Nun

Posted 2016-08-09T15:58:49.743

Reputation: 45 011

lol around 16 times shorter than my answer + 1! (1!==1) – Rohan Jhunjhunwala – 2016-08-09T17:01:47.503

@RohanJhunjhunwala What did you say? – Leaky Nun – 2016-08-09T17:03:03.330

Essentially Java can never compete with Jelly Seeing answers that are 12 bytes long (shorter than any possible java program) is hilarious. So have an upgoat.. – Rohan Jhunjhunwala – 2016-08-09T17:04:40.000

@LeakyNun lol missed the golf :D – Rohan Jhunjhunwala – 2016-08-09T17:05:23.537

21001 outputs 3 when it should return 2 – Daniel – 2016-08-09T19:06:36.247

I give up. This is hard. – noɥʇʎԀʎzɐɹƆ – 2016-08-09T21:00:02.347

5

Java "only" 270 200 196 187 196 138 148 146 bytes!

saved 4 13 countless bytes thanks to Leaky Nun! 1 byte thanks to Micheal Golfed

int m(boolean[]b){int r=0,l=b.length,i,j,k=0,z=r;for(i=0;i<l;i++){if(b[i])for(j=0,k=0;j<l;j++)if(!b[j])k+=i>j?i-j:j-i;if(k>z){r=i;z=k;}}return r;}

Ungolfed

int m(int[] s) {
        int l=s.length,i,j=0,k=0;
    boolean[] b = new boolean[l];
    int[] a = new int[l];
    //see what stalls are open
    for (i = 0; i < s.length; i++) {
        if (s[i] == 0){
            b[i] = true;
        }
    }
    //assign the sum of distance to the a[]
    for (i = 0; i < l; i++) {
        if (b[i]) {
            for (j = 0; j < l; j++) {
                if (!b[j]) {
                    a[i]+= Math.abs(i - j);
                }
            }
        }
    }
    //find the stall the greatest distance away breaking ties based on the furthest left
    for (i = 0; i < l; i++) {
        if (b[i] && (a[i] > k || k == 0)) {
            k = a[i];
            j=i;
        }
    }
    //return the index
    return j;
}

input as an boolean array where true implies an open stall.

Rohan Jhunjhunwala

Posted 2016-08-09T15:58:49.743

Reputation: 2 569

Comments are not for extended discussion; this conversation has been moved to chat.

– Alex A. – 2016-08-09T18:20:48.997

You don't need the array a. – Leaky Nun – 2016-08-10T08:24:11.310

@LeakyNun how do I remove it? – Rohan Jhunjhunwala – 2016-08-10T11:06:49.313

By finding the minimum in one iteration (combine the outer for loops) – Leaky Nun – 2016-08-10T11:07:33.657

oh @LeakyNun will do when I get back today – Rohan Jhunjhunwala – 2016-08-10T11:26:04.287

forgot, but will do tomorrow, @LeakyNun (please do ping me if I forget so I do remember) – Rohan Jhunjhunwala – 2016-08-11T01:09:30.637

You can save a few bytes by changing the loops. for (j = 0; j < l; j++) to for (j = 0; j < l;) and then if (!b[++j]) – Tschallacka – 2016-08-11T06:46:59.590

@MichaelDibbets do u mean !b[j++] – Rohan Jhunjhunwala – 2016-08-11T12:06:32.910

mmh, just occurred, you need 0 index, so at the last occurrence/use of j, in loop you do j++ so the next iteration has it incremented. j = 0, i = ++j then i = 1. j = 0, i = j++ then i = 0 – Tschallacka – 2016-08-11T12:33:21.300

@MichaelDibbets take a look at how I have it now, for the first loop, is that good? – Rohan Jhunjhunwala – 2016-08-11T12:35:10.583

no, that doesn't compile. I'm looking at a way to reconstruct your code that it runs more smooth :-), one sec – Tschallacka – 2016-08-11T12:46:14.160

@MichaelDibbets compiles for me, – Rohan Jhunjhunwala – 2016-08-11T12:47:51.747

Let us continue this discussion in chat.

– Rohan Jhunjhunwala – 2016-08-11T12:47:56.683

You forgot the return statement. – Leaky Nun – 2016-08-12T13:19:03.223

@LeakyNun fixed :D I had it in my IDE just didn't pased all of it. – Rohan Jhunjhunwala – 2016-08-12T13:26:39.870

You don't need to initialize j and k in the beginning. – Leaky Nun – 2016-08-12T14:34:52.467

fixed @LeakyNun – Rohan Jhunjhunwala – 2016-08-12T15:49:57.140

k does need to be initialized – Rohan Jhunjhunwala – 2016-08-12T15:50:08.970

4

Ruby, 79 78 76 + n flag = 77 bytes

Output is 0-based indexing. Input is STDIN line of 0's and 1's.

p (r=0...~/$/).max_by{|i|k=0;$_[i]>?0?0:r.map{|j|k+=$_[j]<?1?0:(j-i).abs};k}

Value Ink

Posted 2016-08-09T15:58:49.743

Reputation: 10 608

10...~/$/ is a nice trick. – Jordan – 2016-08-10T01:26:42.720

2

Perl 84 + 3 (-alp flags) = 87 bytes

for$i(0..$#F){$t=0;map{$t+=abs($i-$_)*$F[$_]}0..$#F;($m,$_)=($t,$i)if$m<$t&&!$F[$i]}

Needs -alp flags to run. Takes a string of 1 and 0 separated by spaces as input. For instance :

perl -alpe '$m=0;for$i(0..$#F){$t=0;map{$t+=abs($i-$_)*$F[$_]}0..$#F;($m,$_)=($t,$i)if$m<$t&&!$F[$i]}' <<< "1 0 1
0 0 1 0 1 1
1 0 1 0 0 0 0 1 1
1 0 0 0 0 0 1 1 0 0 0 0
1 1 1 1 0 0 0 0 0 0 1
1 0"

Note that I added $m=0 at the begining, but that's only to test it on multiple entries.

Dada

Posted 2016-08-09T15:58:49.743

Reputation: 8 279

I count +7: F'' alp. -s aren't counted. – NoOneIsHere – 2016-08-09T17:09:40.670

@NoOneIsHere Hum, indeed, that would be my bad. Thanks – Dada – 2016-08-09T17:13:12.713

2

MATL, 14 bytes

~ftGf!-|Xs&X>)

Try it online!

Output is 1-based.

Explanation

~f     % Implicitly take input. Compute row vector with indices of zeros
t      % Duplicate that
Gf!    % Push input again. Compute column vector of indices of ones
-|     % Absolute differences with broadcast. Gives 2D array with all combinations
Xs     % Sum of each column
&X>    % Arg max. Gives the index of the first maximizer if there are several
)      % Index into row vector of indices of zeros. Implictly display

Luis Mendo

Posted 2016-08-09T15:58:49.743

Reputation: 87 464

2

JavaScript (ES6), 87 86 82 75 bytes

a=>a.map((u,i)=>u||(a.map((v,j)=>u+=v*(i>j?i-j:j-i)),u>x&&(x=d,r=i)),x=0)|r

Takes a boolean array (true/false or 1/0). No point calculating the average distance since they're all using the same common factor, so just calculating the total distance for each stall and finding the first index of the highest one. Edit: Saved 1 byte by using * instead of &&. Saved 5 bytes by finding the highest distance manually based on a comment by @Dendrobium. Saved 7 bytes by reusing u as the pseudo-reduce accumulator based on a comment by @edc65.

Neil

Posted 2016-08-09T15:58:49.743

Reputation: 95 035

79 bytes: a=>(x=0,a.map((o,i)=>x<(t=a.reduce((r,u,j)=>r+(b=i-j)*b*u*!o,0))&&(x=t,r=i)),r) – Dendrobium – 2016-08-09T19:54:44.133

@Dendrobium The question asks for absolute distance; you seem to be calculating RMS distance. – Neil – 2016-08-09T20:45:22.337

1Using an array as input - good idea. Calculating total instead of average - good idea. Using reduce instead of map - mmmm – edc65 – 2016-08-09T21:22:39.853

75: s=>s.map((u,i)=>u||(s.map((w,j)=>u-=w*Math.abs(j-i)),u<x&&(x=u,r=i)),x=0)|r – edc65 – 2016-08-09T21:29:29.693

@Neil Not quite RMS, just squared distances, which shouldn't effect the outcome of the solution unless there are ties in total distances of nonsymmetric inputs (for example 1100011101 ties at 2 and 8 when using absolute, 8 when using squared), not that it matters since it seems that the rules have been clarified and ties are now resolved with the left-most stall... – Dendrobium – 2016-08-09T22:15:46.097

@Dendrobium By my calculations, when given an input of 1,0,1,1,1,1,0,0,0,1,1, squaring picks the leftmost zero but absolute value picks the rightmost zero. – Neil – 2016-08-10T00:13:31.737

@edc65 reduce made more sense in a previous version of the code; I admit it makes less sense now, particularly with your ingenious reuse of u. – Neil – 2016-08-10T00:14:24.833

2

Matlab, 87 bytes

n=input('');k=numel(n);[a b]=ndgrid(1:k);[x y]=max(sum(abs(a-b).*repmat(n,k,1)').*~n);y

Takes array of ones and zeros; uses 1-based indexing.
Like some other answers maximises total not average distance.
Probably there's some more golfing possible...

pajonk

Posted 2016-08-09T15:58:49.743

Reputation: 2 480

1

Ruby, 87 76 bytes

Threw this first draft quickly together, but in the meantime Value Ink had already posted an 80 byte Ruby answer...

edit: took off some bytes with help from Value Ink:

->a{(r=0...a.size).max_by{|i|a[i]?0:r.map{|j|a[j]?(i-j).abs: 0}.reduce(:+)}}

It's an anonymous function that takes an array of truthy/falsy values, like for instance so:

f=->->a{(r=0...a.size).max_by{|i|a[i]?0:r.map{|j|a[j]?(i-j).abs: 0}.reduce(:+)}}
# Test case number 5:
p f[[1, 1, 1, 1, nil, nil, nil, nil, nil, nil, 1]] # => 9

daniero

Posted 2016-08-09T15:58:49.743

Reputation: 17 193

1Assign the initial range to a variable (r=0...a.size) and then map on that instead of using with_index: r.map{|j|a[j]?(i-j).abs: 0}. This should get you 78 bytes. – Value Ink – 2016-08-09T19:07:46.213

@ValueInk Awesome, thanks! With only the function, no assignment, I get 76 bytes

– daniero – 2016-08-09T19:49:49.670

1

J, 27 bytes

(#{:@-.~]/:[:+/]|@-/~#)i.@#

Online interpreter.

Leaky Nun

Posted 2016-08-09T15:58:49.743

Reputation: 45 011

1

Mathematica, 53 bytes

MaximalBy[a=PositionIndex@#;a@0,Tr@Abs[#-a@1]&][[1]]&

Uses 1-based indexing and takes input as a list of 0s and 1s.

alephalpha

Posted 2016-08-09T15:58:49.743

Reputation: 23 988

0

Javascript ES6 - 98 95 91 86 84 88 bytes

Edit: Seems that the leftmost-stall should be used in the case of a tie. Squared distances no longer work, reverted to absolute distance.

(r,x=0,f=g=>r.reduce(g,0))=>f((p,o,i)=>x<(o=f((p,c,j)=>p+c*!o*Math.abs(i-j)))?(x=o,i):p)

Ungolfed:

(r,                            // string input
 x=0,                          // current max distance
 f=g=>r.reduce(g,0))=>         // iterator function
   f((p,o,i)=>                 // for each stall
     x<(o=f((p,c,j)=>          // iterate through all stalls and
       p+c*!o*Math.abs(i-j)))? //   calculate sum of distances from current stall
     (x=o,i):                  // if total dist is greater than x, update x, return index
     p)                        //   else return previous max index

Test runs:

f=(r,x=0,f=g=>r.reduce(g,0))=>f((p,c,i)=>x<(c=+c?0:f((p,c,j)=>p+c*Math.abs(i-j)))?(x=c,i):p)
f([1,0,1])                   // 1
f([0,0,1,0,1,1])             // 0
f([1,0,1,0,0,0,0,1,1])       // 1
f([1,0,0,0,0,0,1,1,0,0,0,0]) // 11
f([1,1,1,1,0,0,0,0,0,0,1])   // 9
f([1,0])                     // 1

Dendrobium

Posted 2016-08-09T15:58:49.743

Reputation: 2 412

0

Lua, 165150 Byes

n=arg[1]n=n:gsub("%|%-","1"):gsub("%| ","0")i=0 for s in n:gmatch("0+")do i=(i<#s)and(#s)or(i)end n,l=n:find(("0"):rep(i))print(n+math.floor((l-n)/2))

This cheats a little using the fact that generally, lua passes a table called arg containing any command line inputs to it.

I'm a bit disappointed that I used a for in loop, but I couldn't think of a smaller way to pull it off.

Also, Because lua, 1 based indexing was used.

Edit Snipped 15 bytes from a wasteful gsub.

ATaco

Posted 2016-08-09T15:58:49.743

Reputation: 7 898

0

C#, 127 bytes

public int G(char[]s){int i=0;var l=s.ToLookup(b=>b,b=>i++);return l['0'].OrderBy(j=>l['1'].Average(p=>Math.Abs(p-j))).Last();}

Test Bed

public static void Main() {
    var respectful = new Respectful();
    foreach (var kvp in testCases) {
        $"{kvp.Key}: Expected {kvp.Value} Actual {respectful.G(kvp.Key.ToCharArray())}".Dump();
    }
}

public static readonly List<KeyValuePair<string, int>> testCases = new List<KeyValuePair<string, int>> {
    new KeyValuePair<string, int>("101", 1),
    new KeyValuePair<string, int>("001011", 0),
    new KeyValuePair<string, int>("101000011", 1),
    new KeyValuePair<string, int>("100000110000", 11),
    new KeyValuePair<string, int>("11110000001", 9),
    new KeyValuePair<string, int>("10", 1),
    new KeyValuePair<string, int>("1001", 1),
};

public class Respectful {
    public int G(char[]s){int i=0;var l=s.ToLookup(b=>b,b=>i++);return l['0'].OrderBy(j=>l['1'].Average(p=>Math.Abs(p-j))).Last();}
}

ErikE

Posted 2016-08-09T15:58:49.743

Reputation: 123