11
\$\begingroup\$

This challenge is based on Downgoat's Adjust your chair.

Challenge

You just adjusted your new chair! It fits you perfectly. However, the wheel is squeaky and you know the repair people will change the adjustment. Problem is, you don't have a ruler, so you'll have to write a program to measure it for you.
Example of an adjustable chair
The repair people can only wait for so long. So your code needs to be as short as possible.

Examples

O
|
|
| _
| |
|_|_
  |
  |
  O

5,3,2,2,1

O
|  _
|  |
|__|__
   |
   |
 __|__
 OOOOO

3,5,2,3,5

O
|      _
|______|______
 ______|______
 OOOOOOOOOOOOO

2,13,1,1,13

Chair parts

The chair has various components:

O  <- Headrest
|
|  <- Backrest
|  _  <- Armrest
|  |
|__|__ <- Seat
   |  
   |   <- Leg
  _|_
  OOO  <- Wheels

Detailed Chair Descriptions

The parts of the chair are:


Headrest: There will always be one headrest above the backrest

O
|

Backrest: The number of | is the Backrest Height

O
|
|

Seat: The number of _ is the Seat Width, there is a | in the middle for the armrest.

__|__

Armrest: The number of | is the Armrest Height. This will be inserted in the middle of the seat.

_
|
|

Leg: The number of | is the Leg Height

|
|

Wheels: The wheels are centred below the legs. If they are more than one, all but the centre wheel will have _ in the line above them.

_ _
OOO

Output

Given a chair, you will be outputting various variables.

The output should be in the following order:

  1. Backrest Height
  2. Seat Width always odd
  3. Armrest Height Always less than backrest height
  4. Leg Height
  5. Wheel count Always less than or equal to seat width and Always odd

The output may have a trailing newline, or be in an array / list form if it is a function.

Leaderboard

/* Configuration */

var QUESTION_ID = 67522; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 43394; // This should be the user ID of the challenge author.

/* App */

var answers = [],
  answers_hash, answer_ids, answer_page = 1,
  more_answers = true,
  comment_page;

function answersUrl(index) {
  return "https://api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function(data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function(data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,]*[^\s,]),.*?(\d+(?:[.]\d+)?)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];

  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if (OVERRIDE_REG.test(c.body))
        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
    });

    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });

  });

  valid.sort(function(a, b) {
    var aB = a.size,
      bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function(a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;

    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
      .replace("{{NAME}}", a.user)
      .replace("{{LANGUAGE}}", a.language)
      .replace("{{SIZE}}", a.size)
      .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    if (/<a/.test(lang)) lang = jQuery(lang).text();

    languages[lang] = languages[lang] || {
      lang: a.language,
      user: a.user,
      size: a.size,
      link: a.link
    };
  });

  var langs = [];
  for (var lang in languages)
    if (languages.hasOwnProperty(lang))
      langs.push(languages[lang]);

  langs.sort(function(a, b) {
    if (a.lang > b.lang) return 1;
    if (a.lang < b.lang) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i) {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
      .replace("{{NAME}}", lang.user)
      .replace("{{SIZE}}", lang.size)
      .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body {
  text-align: left !important
}
#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}
#language-list {
  padding: 10px;
  width: 290px;
  float: left;
}
table thead {
  font-weight: bold;
}
table td {
  padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">
<div id="answer-list">
  <h2>Leaderboard</h2>
  <table class="answer-list">
    <thead>
      <tr>
        <td></td>
        <td>Author</td>
        <td>Language</td>
        <td>Size</td>
      </tr>
    </thead>
    <tbody id="answers">

    </tbody>
  </table>
</div>
<div id="language-list">
  <h2>Winners by Language</h2>
  <table class="language-list">
    <thead>
      <tr>
        <td>Language</td>
        <td>User</td>
        <td>Score</td>
      </tr>
    </thead>
    <tbody id="languages">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr>
      <td>{{PLACE}}</td>
      <td>{{NAME}}</td>
      <td>{{LANGUAGE}}</td>
      <td>{{SIZE}}</td>
      <td><a href="{{LINK}}">Link</a>
      </td>
    </tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr>
      <td>{{LANGUAGE}}</td>
      <td>{{NAME}}</td>
      <td>{{SIZE}}</td>
      <td><a href="{{LINK}}">Link</a>
      </td>
    </tr>
  </tbody>
</table>

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

# Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the leaderboard snippet:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes
\$\endgroup\$
  • \$\begingroup\$ Is the armrest measured? \$\endgroup\$ – J Atkin Dec 23 '15 at 18:38
3
\$\begingroup\$

Lua, 187 Bytes

I think I might be able to golf it some more, but I think this is good at the moment. Also, if the output needs to be comma-separated I can fix that, but this still meets the requirements methinks.

Also, input is fed in one line at a time. After the wheels are input, press enter with an an empty line to finalize input.

c={}i=1t=""while c[i-1]~=""do c[i]=io.read():gsub("%s+","")t=t..c[i]a=(not a and c[i]:find("_")and i or a)s=(not s and c[i]:find("_|_")and i or s)i=i+1 end print(s-1,c[s]:len()-1,s-a,#c-s-2,c[#c-1]:len())

Ungolfed

c={}
i=1
while c[i-1]~=""do 
    c[i]=io.read():gsub("%s+","")          --remove spaces
    a=(not a and c[i]:find"_"and i or a)   --armrest position
    s=(not s and c[i]:find"_|_"and i or s) --seat position
    i=i+1
end
print(s-1, c[s]:len()-1, s-a, #c-s-2, c[#c-1]:len())

(Positions are measured top-to-bottom, so the top 'O' is position 1, and the wheels are the largest position.

  • Backrest height is the position of the seat minus one, compensating for the 'O' at the top.
  • Seat size is the length of th string at the seat's position minus one, compensating for the backrest.
  • Armrest height is the position of the seat minus the position of the armrest.
  • Leg height is the height of the chair (#c) minus the position of the seat minus 2, to compensate for the wheels and seat.
  • Wheel count is the length of the final string.
\$\endgroup\$
3
\$\begingroup\$

Groovy, 161 bytes!!!

Yay!! Not in last!!

f={s->a=s.split(/\n/)
b=a.findIndexOf{it.contains('|_')}
d=b-a.findIndexOf{it.contains('_')}
print"$b,${a[b].count('_')+1},$d,${a.size()-b-2},${s.count('O')-1}"}

Ungolfed:

f={String s ->
    split = s.split(/\n/)
    bottomOfChairBack = split.findIndexOf {it.contains('|_')}
    armHeight = bottomOfChairBack-split.findIndexOf {it.contains('_')}
    width = split[bottomOfChairBack].count('_')+1
    height = split.size() - bottomOfChairBack - 2

    wheelCount = s.count('O')-1
    return [bottomOfChairBack, width, armHeight, height, wheelCount]
}

Tests of ungolfed program:

assert f('''O
|
|
| _
| |
|_|_
  |
  |
  O''') == [5, 3, 2, 2, 1]

assert f('''O
|  _
|  |
|__|__
   |
   |
 __|__
 OOOOO''') == [3,5,2,3,5]

assert f('''O
|  _
|  |
|__|__
   |
   |
 __|__
 OOOOO''') == [3,5,2,3,5]

assert f('''O
|      _
|______|______
 ______|______
 OOOOOOOOOOOOO''') == [2,13,1,1,13]
\$\endgroup\$
2
\$\begingroup\$

Pyth, 57 54 53 50 bytes

Probably can be golfed further. -3 bytes thanks to issacg for the single character string trick.

=kjb.z
=H/k+b\|
-/k\_=G-/k\O2
--/k\|H=Nt/k+bd
N
hG

Explanation:

=kjb.z
=k              Assign k
     z          Input
  jb.           Join list by newlines

=H/k+b\|
=H              Assign H
  / +b\|        Count occurrences of "\n|"
   k            In input
                (Implicit: print backrest height)

-/k\_=G-/k\O2
     =G         Assign G
       -/k\O2   The number of wheels minus 1
-/k\_           Count the number of "_"
                (Implicit: print seat width)

--/k\|H=Nt/k+bd
       =N       Assign N
          /k+bd Count the number of lines starting with " "
         t      Subtract 1 (N is now the leg height)
  /k\|          Count the number of "|"
 -    H         Subtract the "|" for the backrest
-               Subtract leg height
                (Implicit: print armrest height)

N               Print leg height

hG              Print the number of wheels
\$\endgroup\$
  • 1
    \$\begingroup\$ To make a one-character string, use \. So "_" = \_ \$\endgroup\$ – isaacg Dec 24 '15 at 9:36
  • \$\begingroup\$ Ouch, no way am I going to beat this ;) \$\endgroup\$ – J Atkin Dec 24 '15 at 15:23
2
\$\begingroup\$

Perl, 93+2=95 90+1=91 83+1= 84 bytes

Apparently the output doesn't need comma-separating

Invoke with perl -n chair.pl chairInput (1B penalty for the flag).

END{print$b,2+$u-$o,$a,$.-$b-2,$o-1}$u+=s/_//g;$o+=s/O//g;s/^\|//&&$b++&&/\|/&&$a++

Ungolfed:

END{         # Put the END block first to save 1 ;
    print
        $b,   
    2+$u-$o,
    $a,
    $.-$b-2, # $. is the number of lines total
    $o-1
}
$u+=s/_//g; # count _s incrementally
$o+=s/O//g; # count Os incrementally
s/^\|// && $b++ # it's backrest if it starts with |
    && /\|/ && $a++ # and it's armrest if it has another one

Previous version:

Invoke with perl -0n chair.pl < chairInput

s/^\|//&&$b++?/\|/&&$a++:$h++for split"
",$_;$,=",";print$b,2+s/_//g-($o=s/O//g),$a,$h-3,$o-1

Explanation:

s/^\|// && $back++   # the backrest is all lines starting with |
    ? /\|/ && $arm++ # the armrest is all of those lines with another |
    : $height++      # otherwise it counts for the seat height
    for split"
",$_;       # literal newline for 1 byte saved
$,=",";     # output separator
print
    $back,
    2+s/_//g-($o_count=s/O//g),  # you can find the seat size
                                 # from the different between the number
                                 # of Os and _s
    $arm,
    $height-3,
    $o_count-1
\$\endgroup\$
1
\$\begingroup\$

Python 3, 160 158 bytes

This code works but only on the following conditions: 1) armrest height > 0 otherwise the _ count breaks and 2) seat width > 1 otherwise the armrest blocks the width-one seat and the _ count breaks.

def f(s):
 a=s.split("\n");x=[];y=[];l=len(a)
 for i in range(l):
  m=a[i].count("_")
  if m:x+=i,;y+=m,
 return x[1],y[1]+1,x[1]-x[0],l-x[1]-2,s.count("O")-1
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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