#author("2026-07-04T16:37:15+09:00;2023-02-23T23:33:35+09:00","default:vip","vip")
[[練習問題#palindrome]]
#author("2026-07-04T16:37:29+09:00;2023-02-23T23:33:35+09:00","default:vip","vip")
[[練習問題>練習問題#palindrome]]
 #!/usr/bin/python
 # main.py
 from collections import namedtuple
 
 Word = namedtuple('Word', 'letter, pos')
 
 class Solver:
     def __init__(self, s):
         self.copy = s
         self.arr = list(s)
         self.cost = 0
 
     def __change(self, letter, cost, *pos):
         for p in pos:
             self.arr[p] = letter
         self.cost += cost * len(pos)
 
     __change_to_N = lambda self, *pos: self.__change('N', 10, *pos)
     __change_to_O = lambda self, *pos: self.__change('O', 15, *pos)
 
     def to_palindromically(self):
         sz = len(self.arr)
         for i in range(sz//2):
             j = -1 - i
             if self.arr[i] == self.arr[j]:
                 if self.arr[i] == '*':
                     self.__change_to_N(i, j)
             else:
                 if not '*' in (self.arr[i], self.arr[j]):
                     return (self.copy, -1)
                 srt = sorted((Word(self.arr[i], i), Word(self.arr[j], j)))
                 if srt[-1].letter == 'N':
                     self.__change_to_N(srt[0].pos)
                 elif srt[-1].letter == 'O':
                     self.__change_to_O(srt[0].pos)
         if sz & 1 and self.arr[sz//2] == '*':
             self.__change_to_N(sz//2)
         return ''.join(self.arr), self.cost

 #!/usr/bin/python
 # test.py
 from main import Solver
 from collections import namedtuple
 import unittest
 
 T = namedtuple('T', 'input_data, expected')
 
 test_cases = [
   T('NOO*', ('NOON', 10)),
   T('NO*N', ('NOON', 15)),
   T('NO',   ('NO', -1)),
   T('O*O',  ('ONO', 10)),
   T('*********',  ('NNNNNNNNN', 90)),
   T('**********', ('NNNNNNNNNN', 100)),
   T('*O*******',  ('NONNNNNON', 85)),
   T('*O********', ('NONNNNNNON', 95)),
   T('*N*******',  ('NNNNNNNNN', 80)),
   T('*N********', ('NNNNNNNNNN', 90)),
   T('*N*****O*',  ('*N*****O*', -1)),
   T('*N******O*', ('*N******O*', -1)),
   T('****N****',  ('NNNNNNNNN', 80)),
   T('****N*****', ('NNNNNNNNNN', 90)),
   T('****O****',  ('NNNNONNNN', 80)),
   T('****NO****', ('****NO****', -1)),
 ]
 
 class TestSequence(unittest.TestCase):
     pass
 
 def test_generator(input_data, expected):
     def test(self):
         obj = Solver(input_data)
         self.assertEqual(obj.to_palindromically(), expected)
     return test
 
 for case in test_cases:
     name = 'test{0}'.format(case.input_data)
     test = test_generator(case.input_data, case.expected)
     setattr(TestSequence, name, test)
 suite = unittest.TestLoader().loadTestsFromTestCase(TestSequence)
 unittest.TextTestRunner().run(suite)

----
解答2
 cost_table = {'N': 10, 'O': 15}
 
 def palindrome(s):
     size = len(s)
     cost = 0
     res = [''] * size
     for l in range((size+1)//2):
         r = (-l-1)%size
         is_center = 1 if l == r else 0
         c0, c1 = (s[l], s[r]) if s[l] == '*' else (s[r], s[l])
         
         if c0 == '*':
             n_change = 1
             if c1 == '*':
                 c1 = 'N'  # 貪欲
                 n_change = 2 - is_center
             res[l] = res[r] = c1
             cost += cost_table[c1] * n_change
         elif c0 == c1:
             res[l] = res[r] = c1
         else:
             cost = -1
             break
     res_str = ''.join(res) if cost != -1 else s
     return res_str, cost
 
 s = input("input: ").upper().strip()
 print(palindrome(s))

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS