1
0

ロボットの暴走

Last updated at Posted at 2024-03-13

なかなか難しいですね。。。
一応ここまではやってみました。
ですがなかなか思ったとおりにはならず、
予定の時間切れだったので、解答みました。

class Robot():
    def __init__(self,x,y,level):
        self.x = int(x)
        self.y = int(y)
        self.level = int(level)
        
    def levelup(self):
        if self.level < 4:
            self.level += 1
    
    def self_level(self):
        return self.level
    
    def self_x(self):
        return self.x
    
    def self_y(self):
        return self.y
    
    def self_plot(self):
        return (self.x,self.y)
        
    def status(self):
        print(self.x,self.y,self.level)
        
    def move_x(self,plot):
        self.x = plot

    def move_y(self,plot):
        self.y = plot

    def move(self,direction):
        #初期化
        length = 0
        if self.level == 1:
            length = 1
        elif self.level == 2:
            length = 2
        elif self.level == 3:
            length = 5
        elif self.level == 4:
            length = 10
            
        if direction == 'N':
            self.y += length
        elif direction == 'S':
            self.y -= length
        elif direction == 'E':
            self.x += length
        else:
            self.x -= length
            
        

#H=yの上限,W=xの上限,N=ロボット数,K=移動回数
H,W,N,K = map(int,input().split())

# toolbox_plot
toolbox_plots = [(map(int,input().split())) for _ in range(10)]

# robots_start_point
robots = [Robot(*input().split()) for _ in range(N)]

# action
for _ in range(K):
    number, direction = input().split()
    robots[int(number)-1].move(direction)
    
    #tool_boxのplotにいるかどうか
    for toolbox_plot in toolbox_plots:
        self_plot = robots[int(number)-1].self_plot()
        if self_plot == toolbox_plot:
            robots[int(number)-1].levelup()
            break
    

# result
for robot in robots:
    print(robot.status())

一通り、みましたが、
おそらく方向性は多分合ってそうです。
方法はちょっと違いますが。
ということは、
多分上のどこかで間違えているせいで、正しく出力されないんだと思います。
このあとの予定もあるので後で検証するためいったんメモとして残しておきます。
下記は解答。
とりあえず、配列や辞書をうまく使いこなせてないなという感想です

***
あれからちょっと書き直しました。

class Robot:
    def __init__(self,x,y,level):
        self.x = x
        self.y = y
        self.level = level
        
    def levelup(self):
        #前回学習したところ
        self.level = min(self.level+1,4)
    
    def self_plot(self):
        return (self.x,self.y)
        
    def status(self):
        print(self.x,self.y,self.level)

    def move(self,direction):
        #初期化
        length = 0
        if self.level == 1:
            length = 1
        elif self.level == 2:
            length = 2
        elif self.level == 3:
            length = 5
        elif self.level == 4:
            length = 10
            
        if direction == 'N':
            self.y += length
        elif direction == 'S':
            self.y -= length
        elif direction == 'E':
            self.x += length
        else:
            self.x -= length

#H=yの上限,W=xの上限,N=ロボット数,K=移動回数
H,W,N,K = map(int,input().split())

# toolbox_plot
toolbox_plots = [(map(int,input().split())) for _ in range(10)]

# robots_start_point
robots = [Robot(*map(int,input().split())) for _ in range(N)]

# result
for robot in robots:
    print(robot.status())

とりあえず、ロボットの位置が確認できるかどうか確かめたのですが
なぜか下記の出力に。
想定としては、取得した入力されているロボットの位置データが
あっているのでまあいいのかという印象ですが。

2 1 1
None
2 2 1
None
2 2 1
None

とりあえずこれは無視してすすめます

class Robot:
    def __init__(self,x,y,level):
        self.x = x
        self.y = y
        self.level = level
        
    def levelup(self):
        #前回学習したところ
        self.level = min(self.level+1,4)
    
    def self_plot(self):
        return [self.y,self.x]
        
    def status(self):
        print(self.x,self.y,self.level)

    def move(self,direction):
        #初期化
        length = 0
        if self.level == 1:
            length = 1
        elif self.level == 2:
            length = 2
        elif self.level == 3:
            length = 5
        elif self.level == 4:
            length = 10
            
        if direction == 'N':
            self.y += length
        elif direction == 'S':
            self.y -= length
        elif direction == 'E':
            self.x += length
        else:
            self.x -= length

#H=yの上限,W=xの上限,N=ロボット数,K=移動回数
H,W,N,K = map(int,input().split())

# toolbox_plot
toolbox_plots = [(map(int,input().split())) for _ in range(10)]

# robots_start_point
robots = [Robot(*map(int,input().split())) for _ in range(N)]

# action
for _ in range(K):
    number, direction = input().split()
    print('number:',number,'direcetion:',direction)
    robots[int(number)-1].move(direction)
    #tool_boxのplotにいるかどうか
    self_plot = robots[int(number)-1].self_plot()
    print(self_plot)
    for plot in toolbox_plots:
        print(tuple(plot))
        if tuple(plot) == tuple(self_plot):
            print(int(number),':Level Up!')
            robots[int(number)-1].levelup()
            print(robots[int(number)-1].status())
# result
for robot in robots:
    print(robot.status())

出力を出させて
理由がわかったのですが、
どうやら、回答にあるような
self_plotがtoolbox_plotにいるかどうかの判定がうまくいっておらず、
levelupメソッドが発動しないため間違いが起きているようです。
時間になってしまったので、また夜か、明日続きをします。


原因がわかりました。
どうやら、中学の時の学習でxは右方向、yは上方向が正と習ったのですが
この問題の場合だとyは下方向が正になってました。
なのでこうですね

class Robot:
    def __init__(self,x,y,level):
        self.x = int(x)
        self.y = int(y)
        self.level = int(level)
        
    def levelup(self):
        #前回学習したところ
        self.level = min(self.level+1,4)
    
    def self_plot(self):
        plot = [self.x,self.y]
        return plot
        
    def move(self,direction):
        #初期化
        length = 0
        if self.level == 1:
            length = 1
        elif self.level == 2:
            length = 2
        elif self.level == 3:
            length = 5
        elif self.level == 4:
            length = 10
            
        if direction == 'N':
            self.y -= length
        elif direction == 'S':
            self.y += length
        elif direction == 'E':
            self.x += length
        else:
            self.x -= length
        
    def status(self):
        print(self.x,self.y,self.level)


#H=yの上限,W=xの上限,N=ロボット数,K=移動回数
H,W,N,K = map(int,input().split())

# toolbox_plot
toolbox_plots = [(map(int,input().split())) for _ in range(10)]

# robots_start_point
robots = [Robot(*map(int,input().split())) for _ in range(N)]

# action
for _ in range(K):
    number, direction = input().split()
    robots[int(number)-1].move(direction)
    #tool_boxのplotにいるかどうか
    self_plot = robots[int(number)-1].self_plot()
    # if self_plot in toolbox_plotsがうまくいかないので代用
    for plot in toolbox_plots:
        if tuple(plot) == tuple(self_plot):
            robots[int(number)-1].levelup()
# result
for robot in robots:
    print(robot.status())

これでNone以外は正しく出力できました。

3 1 2
None
2 2 1
None
2 4 1
None

Noneは結局原因がわからず、このおかげでPassできないんですよね。。。
(ちなみに内包表記をやめて普通に書いても出る)
ChatGPTに聞いた方法を素直にやってもだめでした。。。
Noneってなんなんだ。。。

statusメソッドのあとにNoneになるような条件式はないはず。。。
時間切れになってしまったので明日。。。?いければやります。


今じーっと見てて気づきました。
クラスのほうにprintメソッド。
で、本編のほうを見るとそっちにもprintメソッド。
もしかして? 本編のほうのprintメソッドを消すと、、、
うまくいきました。

class Robot:
    def __init__(self,x,y,level):
        self.x = int(x)
        self.y = int(y)
        self.level = int(level)
        
    def levelup(self):
        #前回学習したところ
        self.level = min(self.level+1,4)
    
    def self_plot(self):
        plot = [self.x,self.y]
        return plot
        
    def move(self,direction):
        #初期化
        length = 0
        if self.level == 1:
            length = 1
        elif self.level == 2:
            length = 2
        elif self.level == 3:
            length = 5
        elif self.level == 4:
            length = 10
            
        if direction == 'N':
            self.y -= length
        elif direction == 'S':
            self.y += length
        elif direction == 'E':
            self.x += length
        else:
            self.x -= length
        
    def status(self):
        print(self.x,self.y,self.level)


#H=yの上限,W=xの上限,N=ロボット数,K=移動回数
H,W,N,K = map(int,input().split())

# toolbox_plot
toolbox_plots = [(map(int,input().split())) for _ in range(10)]

# robots_start_point
robots = [Robot(*map(int,input().split())) for _ in range(N)]

# action
for _ in range(K):
    number, direction = input().split()
    robots[int(number)-1].move(direction)
    #tool_boxのplotにいるかどうか
    self_plot = robots[int(number)-1].self_plot()
    # if self_plot in toolbox_plotsがうまくいかないので代用
    for plot in toolbox_plots:
        if tuple(plot) == tuple(self_plot):
            robots[int(number)-1].levelup()
# result(ここのprint()をけしてrobot.status()だけにする
for robot in robots:
    robot.status()

あーあ、、、、ちょっとくやしいですね。。。


これで終わりじゃなくて、1つのケースで不合格になりました。
他のケースはあってたらしいです。
ただ、そのケースのデータが膨大な数なので、
いい加減、VSCodeでコードを書いてそこにダウンロードしたデータを入力データとして
使えるようにする、というのをやらないとなと思ってます。
これは明日やります。今日は終わり!


下の新しい書き方を学んでいるうちに上の問題多分解けた気がするのでそのまま修正してみます。
toolbox_plotsに格納するときに配列化できていなかったんですよね。なのでmapの前にlistを入れます。それだけです。

class Robot:
    def __init__(self,x,y,level):
        self.x = int(x)
        self.y = int(y)
        self.level = int(level)
        
    def levelup(self):
        #前回学習したところ
        self.level = min(self.level+1,4)
    
    def self_plot(self):
        plot = [self.x,self.y]
        return plot
        
    def move(self,direction):
        #初期化
        length = 0
        if self.level == 1:
            length = 1
        elif self.level == 2:
            length = 2
        elif self.level == 3:
            length = 5
        elif self.level == 4:
            length = 10
            
        if direction == 'N':
            self.y -= length
        elif direction == 'S':
            self.y += length
        elif direction == 'E':
            self.x += length
        else:
            self.x -= length
        
    def status(self):
        print(self.x,self.y,self.level)


#H=yの上限,W=xの上限,N=ロボット数,K=移動回数
H,W,N,K = map(int,input().split())

# toolbox_plot(ここでlistを追加するのを忘れてたようなので追加)
# 変数にしちゃうのではなくて、配列に入れてから変数にしないといけなかった
toolbox_plots = [list(map(int,input().split())) for _ in range(10)]

# robots_start_point
robots = [Robot(*map(int,input().split())) for _ in range(N)]

# action
for _ in range(K):
    number, direction = input().split()
    robots[int(number)-1].move(direction)
    #tool_boxのplotにいるかどうか
    self_plot = robots[int(number)-1].self_plot()
    # if self_plot in toolbox_plotsがうまくいかないので代用
    for plot in toolbox_plots:
        if tuple(plot) == tuple(self_plot):
            robots[int(number)-1].levelup()
# result(ここのprint()をけしてrobot.status()だけにする
for robot in robots:
    robot.status()

これですべてのケースでうまくいきました。
やっと終わったぜ〜!
なお、listを追加したらこれもうまくいきます。

# if self_plot in toolbox_plotsがうまくいかないので代用
    for plot in toolbox_plots:
        if tuple(plot) == tuple(self_plot):
            robots[int(number)-1].levelup()

つまり、書き方が間違ってたんですね。


新しい書き方も学んでおくことにしました。

とりあえず、上のコードでも自分で問題あるなと思うコードが
こちら。

class Robot:
    #(途中省略)
    def __init__(self,x,y,level):
        self.x = int(x)
        self.y = int(y)
        self.level = int(level)
    #(途中省略)   
    def move(self,direction):
        #初期化
        length = 0
        if self.level == 1:
            length = 1
        elif self.level == 2:
            length = 2
        elif self.level == 3:
            length = 5
        elif self.level == 4:
            length = 10
            
        if direction == 'N':
            self.y -= length
        elif direction == 'S':
            self.y += length
        elif direction == 'E':
            self.x += length
        else:
            self.x -= length
        

要するに、レベルが1のときはこの距離、レベルが2のときはこの距離になる。。。
みたいなことがクラスで表せななかったのでその方法を学ぶと。
クラスの中で辞書を使ってクラス変数?にしちゃうということらしいですね。
私はクラス変数ってなんか総額とか使った回数を保存するものとしか考えていなくて
活用できてなかったです。

解答ではx,yを逆に使ってましたが、私の場合はx,yとして使いたいので逆に。
なんでわざわざ逆にしたのかわからないんですが。
とりあえず1マスとかいうのは英語だとブロックとかいうらしいのでブロックで。
辞書はキーと値で成り立っているので、ブロックリスト[レベル]で、今のロボットのブロックを取得できます。
次に方角も辞書に、配列を加える。

これで8行ぐらいは削除できますね。

class Robot:
    blocklist = {1: 1, 2: 2, 3: 5, 4: 10}
    dirs = {"N": [0, -1], "S": [0, 1], "E": [1, 0], "W": [-1, 0]}
    def __init__(self,x,y,level):
        self.x = int(x)
        self.y = int(y)
        self.level = int(level)
        #ここから追加
        self.blocks = self.blocklist[self.level]
   
    def move(self,direction):
        value = self.dirs[direction]

        self.x += value[0] * self.blocks
        self.y += value[1] * self.blocks
        
    def levelup(self):
        self.level = min(self.level+1, 4)
        self.blocks = self.blocklist[self.level]

こうですね。

他のとドッキングしたのがこちら。

class Robot:
    blocklist = {1: 1, 2: 2, 3: 5, 4: 10}
    dirs = {"N": [0, -1], "S": [0, 1], "E": [1, 0], "W": [-1, 0]}
    def __init__(self,x,y,level):
        self.x = int(x)
        self.y = int(y)
        self.level = int(level)
        #ここから追加
        self.blocks = self.blocklist[self.level]
   
    def move(self,direction):
        value = self.dirs[direction]

        self.x += value[0] * self.blocks
        self.y += value[1] * self.blocks
        
    def levelup(self):
        self.level = min(self.level+1, 4)
        self.blocks = self.blocklist[self.level]
    
    def self_plot(self):
        plot = [self.x,self.y]
        return plot
        
    def status(self):
        print(self.x,self.y,self.level)


#H=yの上限,W=xの上限,N=ロボット数,K=移動回数
H,W,N,K = map(int,input().split())

# toolbox_plot
toolbox_plots = [list(map(int,input().split())) for _ in range(10)]

# robots_start_point
robots = [Robot(*map(int,input().split())) for _ in range(N)]

# action
for _ in range(K):
    number, direction = input().split()
    robots[int(number)-1].move(direction)
    #tool_boxのplotにいるかどうか
    self_plot = robots[int(number)-1].self_plot()
    if self_plot in toolbox_plots:
            robots[int(number)-1].levelup()
# result
for robot in robots:
    robot.status()

もちろんすべてのケースでうまくいきました。
いやあ〜!スッキリ!

学んだこととして

・クラス変数は色んな用途に使える
・辞書のキー:値はレベル1のときはこれ、レベル2のときはこれとか
 ある条件のときはこれ、ある条件のときはこれとかを登録しておいて
辞書のキーをもとに出力ができるので便利
・辞書は配列も登録できちゃうので、座標(方角とかでも)に便利

ここまでやってきてめちゃくちゃレベルアップした感ありありです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0